Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2018 Vladimir Medvedkin <medvedkinv@gmail.com>
3 : : * Copyright(c) 2019 Intel Corporation
4 : : */
5 : :
6 : : #include <stdint.h>
7 : : #include <stdio.h>
8 : :
9 : : #include <rte_debug.h>
10 : : #include <rte_malloc.h>
11 : : #include <rte_errno.h>
12 : : #include <rte_vect.h>
13 : : #include <rte_cpuflags.h>
14 : :
15 : : #include <rte_rib.h>
16 : : #include <rte_fib.h>
17 : : #include "dir24_8.h"
18 : : #include "fib_log.h"
19 : :
20 : : #ifdef CC_AVX512_SUPPORT
21 : :
22 : : #include "dir24_8_avx512.h"
23 : :
24 : : #elif defined(RTE_RISCV_FEATURE_V)
25 : :
26 : : #include "dir24_8_rvv.h"
27 : :
28 : : #endif /* CC_AVX512_SUPPORT */
29 : :
30 : : #define DIR24_8_NAMESIZE 64
31 : :
32 : : #define ROUNDUP(x, y) RTE_ALIGN_CEIL(x, (1 << (32 - y)))
33 : :
34 : : static inline rte_fib_lookup_fn_t
35 : : get_scalar_fn(enum rte_fib_dir24_8_nh_sz nh_sz, bool be_addr)
36 : : {
37 [ + + + + : 6 : switch (nh_sz) {
- ]
38 : 1 : case RTE_FIB_DIR24_8_1B:
39 [ - - + - ]: 1 : return be_addr ? dir24_8_lookup_bulk_1b_be : dir24_8_lookup_bulk_1b;
40 : 1 : case RTE_FIB_DIR24_8_2B:
41 [ - - + - ]: 1 : return be_addr ? dir24_8_lookup_bulk_2b_be : dir24_8_lookup_bulk_2b;
42 : 3 : case RTE_FIB_DIR24_8_4B:
43 [ - - + - ]: 3 : return be_addr ? dir24_8_lookup_bulk_4b_be : dir24_8_lookup_bulk_4b;
44 : 1 : case RTE_FIB_DIR24_8_8B:
45 [ - - + - ]: 1 : return be_addr ? dir24_8_lookup_bulk_8b_be : dir24_8_lookup_bulk_8b;
46 : : default:
47 : : return NULL;
48 : : }
49 : : }
50 : :
51 : : static inline rte_fib_lookup_fn_t
52 : : get_scalar_fn_inlined(enum rte_fib_dir24_8_nh_sz nh_sz, bool be_addr)
53 : : {
54 : 0 : switch (nh_sz) {
55 : 0 : case RTE_FIB_DIR24_8_1B:
56 [ # # ]: 0 : return be_addr ? dir24_8_lookup_bulk_0_be : dir24_8_lookup_bulk_0;
57 : 0 : case RTE_FIB_DIR24_8_2B:
58 [ # # ]: 0 : return be_addr ? dir24_8_lookup_bulk_1_be : dir24_8_lookup_bulk_1;
59 : 0 : case RTE_FIB_DIR24_8_4B:
60 [ # # ]: 0 : return be_addr ? dir24_8_lookup_bulk_2_be : dir24_8_lookup_bulk_2;
61 : 0 : case RTE_FIB_DIR24_8_8B:
62 [ # # ]: 0 : return be_addr ? dir24_8_lookup_bulk_3_be : dir24_8_lookup_bulk_3;
63 : : default:
64 : : return NULL;
65 : : }
66 : : }
67 : :
68 : : static inline rte_fib_lookup_fn_t
69 : 6 : get_vector_fn(enum rte_fib_dir24_8_nh_sz nh_sz, bool be_addr)
70 : : {
71 : : #ifdef CC_AVX512_SUPPORT
72 [ + - + - ]: 12 : if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_AVX512F) <= 0 ||
73 [ + - ]: 12 : rte_cpu_get_flag_enabled(RTE_CPUFLAG_AVX512DQ) <= 0 ||
74 : 6 : rte_vect_get_max_simd_bitwidth() < RTE_VECT_SIMD_512)
75 : 6 : return NULL;
76 : :
77 [ # # # # ]: 0 : if (be_addr && rte_cpu_get_flag_enabled(RTE_CPUFLAG_AVX512BW) <= 0)
78 : : return NULL;
79 : :
80 [ # # # # : 0 : switch (nh_sz) {
# ]
81 : 0 : case RTE_FIB_DIR24_8_1B:
82 [ # # ]: 0 : return be_addr ? rte_dir24_8_vec_lookup_bulk_1b_be :
83 : : rte_dir24_8_vec_lookup_bulk_1b;
84 : 0 : case RTE_FIB_DIR24_8_2B:
85 [ # # ]: 0 : return be_addr ? rte_dir24_8_vec_lookup_bulk_2b_be :
86 : : rte_dir24_8_vec_lookup_bulk_2b;
87 : 0 : case RTE_FIB_DIR24_8_4B:
88 [ # # ]: 0 : return be_addr ? rte_dir24_8_vec_lookup_bulk_4b_be :
89 : : rte_dir24_8_vec_lookup_bulk_4b;
90 : 0 : case RTE_FIB_DIR24_8_8B:
91 [ # # ]: 0 : return be_addr ? rte_dir24_8_vec_lookup_bulk_8b_be :
92 : : rte_dir24_8_vec_lookup_bulk_8b;
93 : : default:
94 : : return NULL;
95 : : }
96 : : #elif defined(RTE_RISCV_FEATURE_V)
97 : : RTE_SET_USED(be_addr);
98 : : if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_RISCV_ISA_V) <= 0)
99 : : return NULL;
100 : : switch (nh_sz) {
101 : : case RTE_FIB_DIR24_8_1B:
102 : : return rte_dir24_8_vec_lookup_bulk_1b;
103 : : case RTE_FIB_DIR24_8_2B:
104 : : return rte_dir24_8_vec_lookup_bulk_2b;
105 : : case RTE_FIB_DIR24_8_4B:
106 : : return rte_dir24_8_vec_lookup_bulk_4b;
107 : : case RTE_FIB_DIR24_8_8B:
108 : : return rte_dir24_8_vec_lookup_bulk_8b;
109 : : default:
110 : : return NULL;
111 : : }
112 : : #else
113 : : RTE_SET_USED(nh_sz);
114 : : RTE_SET_USED(be_addr);
115 : : #endif
116 : : return NULL;
117 : : }
118 : :
119 : : rte_fib_lookup_fn_t
120 : 6 : dir24_8_get_lookup_fn(void *p, enum rte_fib_lookup_type type, bool be_addr)
121 : : {
122 : : enum rte_fib_dir24_8_nh_sz nh_sz;
123 : : rte_fib_lookup_fn_t ret_fn;
124 : : struct dir24_8_tbl *dp = p;
125 : :
126 [ + - ]: 6 : if (dp == NULL)
127 : : return NULL;
128 : :
129 : 6 : nh_sz = dp->nh_sz;
130 : :
131 [ - - - - : 6 : switch (type) {
+ - ]
132 [ # # # # : 0 : case RTE_FIB_LOOKUP_DIR24_8_SCALAR_MACRO:
# ]
133 : : return get_scalar_fn(nh_sz, be_addr);
134 [ # # # # : 0 : case RTE_FIB_LOOKUP_DIR24_8_SCALAR_INLINE:
# ]
135 : : return get_scalar_fn_inlined(nh_sz, be_addr);
136 : 0 : case RTE_FIB_LOOKUP_DIR24_8_SCALAR_UNI:
137 [ # # ]: 0 : return be_addr ? dir24_8_lookup_bulk_uni_be : dir24_8_lookup_bulk_uni;
138 : 0 : case RTE_FIB_LOOKUP_DIR24_8_VECTOR_AVX512:
139 : 0 : return get_vector_fn(nh_sz, be_addr);
140 : 6 : case RTE_FIB_LOOKUP_DEFAULT:
141 : 6 : ret_fn = get_vector_fn(nh_sz, be_addr);
142 [ + - ]: 6 : return ret_fn != NULL ? ret_fn : get_scalar_fn(nh_sz, be_addr);
143 : : default:
144 : : return NULL;
145 : : }
146 : :
147 : : return NULL;
148 : : }
149 : :
150 : : static void
151 : 2593 : write_to_fib(void *ptr, uint64_t val, enum rte_fib_dir24_8_nh_sz size, int n)
152 : : {
153 : : int i;
154 : : uint8_t *ptr8 = (uint8_t *)ptr;
155 : : uint16_t *ptr16 = (uint16_t *)ptr;
156 : : uint32_t *ptr32 = (uint32_t *)ptr;
157 : : uint64_t *ptr64 = (uint64_t *)ptr;
158 : :
159 [ + + + + : 2593 : switch (size) {
- ]
160 : : case RTE_FIB_DIR24_8_1B:
161 [ + + ]: 67110531 : for (i = 0; i < n; i++)
162 : 67110396 : ptr8[i] = (uint8_t)val;
163 : : break;
164 : : case RTE_FIB_DIR24_8_2B:
165 [ + + ]: 67110531 : for (i = 0; i < n; i++)
166 : 67110396 : ptr16[i] = (uint16_t)val;
167 : : break;
168 : : case RTE_FIB_DIR24_8_4B:
169 [ + + ]: 100815257 : for (i = 0; i < n; i++)
170 : 100813069 : ptr32[i] = (uint32_t)val;
171 : : break;
172 : : case RTE_FIB_DIR24_8_8B:
173 [ + + ]: 67110531 : for (i = 0; i < n; i++)
174 : 67110396 : ptr64[i] = (uint64_t)val;
175 : : break;
176 : : }
177 : 2593 : }
178 : :
179 : : static int
180 : 521 : tbl8_get_idx(struct dir24_8_tbl *dp)
181 : : {
182 : : uint32_t i;
183 : : int bit_idx;
184 : :
185 [ + - ]: 521 : for (i = 0; (i < (dp->number_tbl8s >> BITMAP_SLAB_BIT_SIZE_LOG2)) &&
186 [ - + ]: 521 : (dp->tbl8_idxes[i] == UINT64_MAX); i++)
187 : : ;
188 [ + - ]: 521 : if (i < (dp->number_tbl8s >> BITMAP_SLAB_BIT_SIZE_LOG2)) {
189 : 521 : bit_idx = rte_ctz64(~dp->tbl8_idxes[i]);
190 : 521 : dp->tbl8_idxes[i] |= (1ULL << bit_idx);
191 : 521 : return (i << BITMAP_SLAB_BIT_SIZE_LOG2) + bit_idx;
192 : : }
193 : : return -ENOSPC;
194 : : }
195 : :
196 : : static inline void
197 : : tbl8_free_idx(struct dir24_8_tbl *dp, int idx)
198 : : {
199 : 520 : dp->tbl8_idxes[idx >> BITMAP_SLAB_BIT_SIZE_LOG2] &=
200 : 520 : ~(1ULL << (idx & BITMAP_SLAB_BITMASK));
201 : : }
202 : :
203 : : static int
204 : 521 : tbl8_alloc(struct dir24_8_tbl *dp, uint64_t nh)
205 : : {
206 : : int64_t tbl8_idx;
207 : : uint8_t *tbl8_ptr;
208 : :
209 : 521 : tbl8_idx = tbl8_get_idx(dp);
210 : :
211 : : /* If there are no tbl8 groups try to reclaim one. */
212 [ - + - - : 521 : if (unlikely(tbl8_idx == -ENOSPC && dp->dq &&
- - ]
213 : : !rte_rcu_qsbr_dq_reclaim(dp->dq, 1, NULL, NULL, NULL)))
214 : 0 : tbl8_idx = tbl8_get_idx(dp);
215 : :
216 [ - + ]: 521 : if (tbl8_idx < 0)
217 : 0 : return tbl8_idx;
218 : 521 : tbl8_ptr = (uint8_t *)dp->tbl8 +
219 : 521 : ((tbl8_idx * DIR24_8_TBL8_GRP_NUM_ENT) <<
220 : 521 : dp->nh_sz);
221 : : /*Init tbl8 entries with nexthop from tbl24*/
222 : 521 : write_to_fib((void *)tbl8_ptr, nh|
223 : : DIR24_8_EXT_ENT, dp->nh_sz,
224 : : DIR24_8_TBL8_GRP_NUM_ENT);
225 : 521 : dp->cur_tbl8s++;
226 : 521 : return tbl8_idx;
227 : : }
228 : :
229 : : static void
230 : 520 : tbl8_cleanup_and_free(struct dir24_8_tbl *dp, uint64_t tbl8_idx)
231 : : {
232 : 520 : uint8_t *ptr = (uint8_t *)dp->tbl8 + (tbl8_idx * DIR24_8_TBL8_GRP_NUM_ENT << dp->nh_sz);
233 : :
234 : 520 : memset(ptr, 0, DIR24_8_TBL8_GRP_NUM_ENT << dp->nh_sz);
235 : 520 : tbl8_free_idx(dp, tbl8_idx);
236 : 520 : dp->cur_tbl8s--;
237 : 520 : }
238 : :
239 : : static void
240 : 0 : __rcu_qsbr_free_resource(void *p, void *data, unsigned int n __rte_unused)
241 : : {
242 : : struct dir24_8_tbl *dp = p;
243 : 0 : uint64_t tbl8_idx = *(uint64_t *)data;
244 : :
245 : 0 : tbl8_cleanup_and_free(dp, tbl8_idx);
246 : 0 : }
247 : :
248 : : static void
249 : 1161 : tbl8_recycle(struct dir24_8_tbl *dp, uint32_t ip, uint64_t tbl8_idx)
250 : : {
251 : : uint32_t i;
252 : : uint64_t nh;
253 : : uint8_t *ptr8;
254 : : uint16_t *ptr16;
255 : : uint32_t *ptr32;
256 : : uint64_t *ptr64;
257 : :
258 [ + + + + : 1161 : switch (dp->nh_sz) {
- ]
259 : 34 : case RTE_FIB_DIR24_8_1B:
260 : 34 : ptr8 = &((uint8_t *)dp->tbl8)[tbl8_idx *
261 : : DIR24_8_TBL8_GRP_NUM_ENT];
262 : 34 : nh = *ptr8;
263 [ + + ]: 1038 : for (i = 1; i < DIR24_8_TBL8_GRP_NUM_ENT; i++) {
264 [ + + ]: 1036 : if (nh != ptr8[i])
265 : : return;
266 : : }
267 : 2 : ((uint8_t *)dp->tbl24)[ip >> 8] =
268 : 2 : nh & ~DIR24_8_EXT_ENT;
269 : 2 : break;
270 : 34 : case RTE_FIB_DIR24_8_2B:
271 : 34 : ptr16 = &((uint16_t *)dp->tbl8)[tbl8_idx *
272 : : DIR24_8_TBL8_GRP_NUM_ENT];
273 : 34 : nh = *ptr16;
274 [ + + ]: 1038 : for (i = 1; i < DIR24_8_TBL8_GRP_NUM_ENT; i++) {
275 [ + + ]: 1036 : if (nh != ptr16[i])
276 : : return;
277 : : }
278 : 2 : ((uint16_t *)dp->tbl24)[ip >> 8] =
279 : 2 : nh & ~DIR24_8_EXT_ENT;
280 : 2 : break;
281 : 1059 : case RTE_FIB_DIR24_8_4B:
282 : 1059 : ptr32 = &((uint32_t *)dp->tbl8)[tbl8_idx *
283 : : DIR24_8_TBL8_GRP_NUM_ENT];
284 : 1059 : nh = *ptr32;
285 [ + + ]: 181358 : for (i = 1; i < DIR24_8_TBL8_GRP_NUM_ENT; i++) {
286 [ + + ]: 180844 : if (nh != ptr32[i])
287 : : return;
288 : : }
289 : 514 : ((uint32_t *)dp->tbl24)[ip >> 8] =
290 : 514 : nh & ~DIR24_8_EXT_ENT;
291 : 514 : break;
292 : 34 : case RTE_FIB_DIR24_8_8B:
293 : 34 : ptr64 = &((uint64_t *)dp->tbl8)[tbl8_idx *
294 : : DIR24_8_TBL8_GRP_NUM_ENT];
295 : 34 : nh = *ptr64;
296 [ + + ]: 1038 : for (i = 1; i < DIR24_8_TBL8_GRP_NUM_ENT; i++) {
297 [ + + ]: 1036 : if (nh != ptr64[i])
298 : : return;
299 : : }
300 : 2 : ((uint64_t *)dp->tbl24)[ip >> 8] =
301 : 2 : nh & ~DIR24_8_EXT_ENT;
302 : 2 : break;
303 : : }
304 : :
305 [ + + ]: 520 : if (dp->v == NULL) {
306 : 8 : tbl8_cleanup_and_free(dp, tbl8_idx);
307 [ + - ]: 512 : } else if (dp->rcu_mode == RTE_FIB_QSBR_MODE_SYNC) {
308 : 512 : rte_rcu_qsbr_synchronize(dp->v, RTE_QSBR_THRID_INVALID);
309 : 512 : tbl8_cleanup_and_free(dp, tbl8_idx);
310 : : } else { /* RTE_FIB_QSBR_MODE_DQ */
311 [ # # ]: 0 : if (rte_rcu_qsbr_dq_enqueue(dp->dq, &tbl8_idx))
312 : 0 : FIB_LOG(ERR, "Failed to push QSBR FIFO");
313 : : }
314 : : }
315 : :
316 : : static int
317 : 1537 : install_to_fib(struct dir24_8_tbl *dp, uint32_t ledge, uint32_t redge,
318 : : uint64_t next_hop)
319 : : {
320 : : uint64_t tbl24_tmp;
321 : : int tbl8_idx;
322 : : int tmp_tbl8_idx;
323 : : uint8_t *tbl8_ptr;
324 : : uint32_t len;
325 : :
326 [ + - ]: 1537 : len = ((ledge == 0) && (redge == 0)) ? 1 << 24 :
327 : 1537 : ((redge & DIR24_8_TBL24_MASK) - ROUNDUP(ledge, 24)) >> 8;
328 : :
329 [ + + - + ]: 1537 : if (((ledge >> 8) != (redge >> 8)) || (len == 1 << 24)) {
330 [ + + ]: 384 : if ((ROUNDUP(ledge, 24) - ledge) != 0) {
331 [ - + ]: 8 : tbl24_tmp = get_tbl24(dp, ledge, dp->nh_sz);
332 [ - + ]: 8 : if ((tbl24_tmp & DIR24_8_EXT_ENT) !=
333 : : DIR24_8_EXT_ENT) {
334 : : /**
335 : : * Make sure there is space for two TBL8.
336 : : * This is necessary when installing range that
337 : : * needs tbl8 for ledge and redge.
338 : : */
339 : 0 : tbl8_idx = tbl8_alloc(dp, tbl24_tmp);
340 : 0 : tmp_tbl8_idx = tbl8_get_idx(dp);
341 [ # # ]: 0 : if (tbl8_idx < 0)
342 : : return -ENOSPC;
343 [ # # ]: 0 : else if (tmp_tbl8_idx < 0) {
344 : : tbl8_free_idx(dp, tbl8_idx);
345 : 0 : return -ENOSPC;
346 : : }
347 : : tbl8_free_idx(dp, tmp_tbl8_idx);
348 : : /*update dir24 entry with tbl8 index*/
349 : 0 : write_to_fib(get_tbl24_p(dp, ledge,
350 : 0 : dp->nh_sz), (tbl8_idx << 1)|
351 : : DIR24_8_EXT_ENT,
352 : : dp->nh_sz, 1);
353 : : } else
354 : 8 : tbl8_idx = tbl24_tmp >> 1;
355 : 8 : tbl8_ptr = (uint8_t *)dp->tbl8 +
356 : 8 : (((tbl8_idx * DIR24_8_TBL8_GRP_NUM_ENT) +
357 : 8 : (ledge & ~DIR24_8_TBL24_MASK)) <<
358 : 8 : dp->nh_sz);
359 : : /*update tbl8 with new next hop*/
360 : 8 : write_to_fib((void *)tbl8_ptr, (next_hop << 1)|
361 : : DIR24_8_EXT_ENT,
362 : 8 : dp->nh_sz, ROUNDUP(ledge, 24) - ledge);
363 : 8 : tbl8_recycle(dp, ledge, tbl8_idx);
364 : : }
365 : 384 : write_to_fib(get_tbl24_p(dp, ROUNDUP(ledge, 24), dp->nh_sz),
366 : : next_hop << 1, dp->nh_sz, len);
367 [ - + ]: 384 : if (redge & ~DIR24_8_TBL24_MASK) {
368 [ # # ]: 0 : tbl24_tmp = get_tbl24(dp, redge, dp->nh_sz);
369 [ # # ]: 0 : if ((tbl24_tmp & DIR24_8_EXT_ENT) !=
370 : : DIR24_8_EXT_ENT) {
371 : 0 : tbl8_idx = tbl8_alloc(dp, tbl24_tmp);
372 [ # # ]: 0 : if (tbl8_idx < 0)
373 : : return -ENOSPC;
374 : : /*update dir24 entry with tbl8 index*/
375 : 0 : write_to_fib(get_tbl24_p(dp, redge,
376 : 0 : dp->nh_sz), (tbl8_idx << 1)|
377 : : DIR24_8_EXT_ENT,
378 : : dp->nh_sz, 1);
379 : : } else
380 : 0 : tbl8_idx = tbl24_tmp >> 1;
381 : 0 : tbl8_ptr = (uint8_t *)dp->tbl8 +
382 : 0 : ((tbl8_idx * DIR24_8_TBL8_GRP_NUM_ENT) <<
383 : 0 : dp->nh_sz);
384 : : /*update tbl8 with new next hop*/
385 : 0 : write_to_fib((void *)tbl8_ptr, (next_hop << 1)|
386 : : DIR24_8_EXT_ENT,
387 : 0 : dp->nh_sz, redge & ~DIR24_8_TBL24_MASK);
388 : 0 : tbl8_recycle(dp, redge, tbl8_idx);
389 : : }
390 [ + - ]: 1153 : } else if ((redge - ledge) != 0) {
391 [ + + ]: 1153 : tbl24_tmp = get_tbl24(dp, ledge, dp->nh_sz);
392 [ + + ]: 1153 : if ((tbl24_tmp & DIR24_8_EXT_ENT) !=
393 : : DIR24_8_EXT_ENT) {
394 : 521 : tbl8_idx = tbl8_alloc(dp, tbl24_tmp);
395 [ + - ]: 521 : if (tbl8_idx < 0)
396 : : return -ENOSPC;
397 : : /*update dir24 entry with tbl8 index*/
398 : 521 : write_to_fib(get_tbl24_p(dp, ledge, dp->nh_sz),
399 : 521 : (tbl8_idx << 1)|
400 : : DIR24_8_EXT_ENT,
401 : : dp->nh_sz, 1);
402 : : } else
403 : 632 : tbl8_idx = tbl24_tmp >> 1;
404 : 1153 : tbl8_ptr = (uint8_t *)dp->tbl8 +
405 : 1153 : (((tbl8_idx * DIR24_8_TBL8_GRP_NUM_ENT) +
406 : 1153 : (ledge & ~DIR24_8_TBL24_MASK)) <<
407 : 1153 : dp->nh_sz);
408 : : /*update tbl8 with new next hop*/
409 : 1153 : write_to_fib((void *)tbl8_ptr, (next_hop << 1)|
410 : : DIR24_8_EXT_ENT,
411 : 1153 : dp->nh_sz, redge - ledge);
412 : 1153 : tbl8_recycle(dp, ledge, tbl8_idx);
413 : : }
414 : : return 0;
415 : : }
416 : :
417 : : static int
418 : 1537 : modify_fib(struct dir24_8_tbl *dp, struct rte_rib *rib, uint32_t ip,
419 : : uint8_t depth, uint64_t next_hop)
420 : : {
421 : : struct rte_rib_node *tmp = NULL;
422 : : uint32_t ledge, redge, tmp_ip;
423 : : int ret;
424 : : uint8_t tmp_depth;
425 : :
426 : : ledge = ip;
427 : : do {
428 : 1785 : tmp = rte_rib_get_nxt(rib, ip, depth, tmp,
429 : : RTE_RIB_GET_NXT_COVER);
430 [ + + ]: 1785 : if (tmp != NULL) {
431 : 248 : rte_rib_get_depth(tmp, &tmp_depth);
432 [ - + ]: 248 : if (tmp_depth == depth)
433 : 0 : continue;
434 : 248 : rte_rib_get_ip(tmp, &tmp_ip);
435 [ + - ]: 248 : redge = tmp_ip & rte_rib_depth_to_mask(tmp_depth);
436 [ + - ]: 248 : if (ledge == redge) {
437 : 248 : ledge = redge +
438 : 248 : (uint32_t)(1ULL << (32 - tmp_depth));
439 : 248 : continue;
440 : : }
441 : 0 : ret = install_to_fib(dp, ledge, redge,
442 : : next_hop);
443 [ # # ]: 0 : if (ret != 0)
444 : 0 : return ret;
445 : 0 : ledge = redge +
446 : 0 : (uint32_t)(1ULL << (32 - tmp_depth));
447 : : /*
448 : : * we got to the end of address space
449 : : * and wrapped around
450 : : */
451 [ # # ]: 0 : if (ledge == 0)
452 : : break;
453 : : } else {
454 : 1537 : redge = ip + (uint32_t)(1ULL << (32 - depth));
455 [ + - ]: 1537 : if (ledge == redge && ledge != 0)
456 : : break;
457 : 1537 : ret = install_to_fib(dp, ledge, redge,
458 : : next_hop);
459 [ - + ]: 1537 : if (ret != 0)
460 : 0 : return ret;
461 : : }
462 [ + + ]: 1785 : } while (tmp);
463 : :
464 : : return 0;
465 : : }
466 : :
467 : : int
468 : 1537 : dir24_8_modify(struct rte_fib *fib, uint32_t ip, uint8_t depth,
469 : : uint64_t next_hop, int op)
470 : : {
471 : : struct dir24_8_tbl *dp;
472 : : struct rte_rib *rib;
473 : : struct rte_rib_node *tmp = NULL;
474 : : struct rte_rib_node *node;
475 : : struct rte_rib_node *parent;
476 : : int ret = 0;
477 : : uint64_t par_nh, node_nh;
478 : :
479 [ + - ]: 1537 : if ((fib == NULL) || (depth > RTE_FIB_MAXDEPTH))
480 : : return -EINVAL;
481 : :
482 : 1537 : dp = rte_fib_get_dp(fib);
483 : 1537 : rib = rte_fib_get_rib(fib);
484 : : RTE_ASSERT((dp != NULL) && (rib != NULL));
485 : :
486 [ + - ]: 1537 : if (next_hop > get_max_nh(dp->nh_sz))
487 : : return -EINVAL;
488 : :
489 : 1537 : ip &= rte_rib_depth_to_mask(depth);
490 : :
491 : 1537 : node = rte_rib_lookup_exact(rib, ip, depth);
492 [ + + - ]: 1537 : switch (op) {
493 : 769 : case RTE_FIB_ADD:
494 [ - + ]: 769 : if (node != NULL) {
495 : 0 : rte_rib_get_nh(node, &node_nh);
496 [ # # ]: 0 : if (node_nh == next_hop)
497 : : return 0;
498 : 0 : ret = modify_fib(dp, rib, ip, depth, next_hop);
499 [ # # ]: 0 : if (ret == 0)
500 : 0 : rte_rib_set_nh(node, next_hop);
501 : 0 : return 0;
502 : : }
503 [ + + ]: 769 : if (depth > 24) {
504 : 577 : tmp = rte_rib_get_nxt(rib, ip, 24, NULL,
505 : : RTE_RIB_GET_NXT_COVER);
506 [ + + ]: 577 : if ((tmp == NULL) &&
507 [ + - ]: 521 : (dp->rsvd_tbl8s >= dp->number_tbl8s))
508 : : return -ENOSPC;
509 : :
510 : : }
511 : 769 : node = rte_rib_insert(rib, ip, depth);
512 [ - + ]: 769 : if (node == NULL)
513 : 0 : return -rte_errno;
514 : 769 : rte_rib_set_nh(node, next_hop);
515 : 769 : parent = rte_rib_lookup_parent(node);
516 [ + + ]: 769 : if (parent != NULL) {
517 : 124 : rte_rib_get_nh(parent, &par_nh);
518 [ + - ]: 124 : if (par_nh == next_hop)
519 : : return 0;
520 : : }
521 : 769 : ret = modify_fib(dp, rib, ip, depth, next_hop);
522 [ - + ]: 769 : if (ret != 0) {
523 : 0 : rte_rib_remove(rib, ip, depth);
524 : 0 : return ret;
525 : : }
526 [ + + ]: 769 : if ((depth > 24) && (tmp == NULL))
527 : 521 : dp->rsvd_tbl8s++;
528 : : return 0;
529 : 768 : case RTE_FIB_DEL:
530 [ + - ]: 768 : if (node == NULL)
531 : : return -ENOENT;
532 : :
533 : 768 : parent = rte_rib_lookup_parent(node);
534 [ + + ]: 768 : if (parent != NULL) {
535 : 124 : rte_rib_get_nh(parent, &par_nh);
536 : 124 : rte_rib_get_nh(node, &node_nh);
537 [ + - ]: 124 : if (par_nh != node_nh)
538 : 124 : ret = modify_fib(dp, rib, ip, depth, par_nh);
539 : : } else
540 : 644 : ret = modify_fib(dp, rib, ip, depth, dp->def_nh);
541 [ + - ]: 768 : if (ret == 0) {
542 : 768 : rte_rib_remove(rib, ip, depth);
543 [ + + ]: 768 : if (depth > 24) {
544 : 576 : tmp = rte_rib_get_nxt(rib, ip, 24, NULL,
545 : : RTE_RIB_GET_NXT_COVER);
546 [ + + ]: 576 : if (tmp == NULL)
547 : 520 : dp->rsvd_tbl8s--;
548 : : }
549 : : }
550 : : return ret;
551 : : default:
552 : : break;
553 : : }
554 : : return -EINVAL;
555 : : }
556 : :
557 : : void *
558 : 8 : dir24_8_create(const char *name, int socket_id, struct rte_fib_conf *fib_conf)
559 : : {
560 : : char mem_name[DIR24_8_NAMESIZE];
561 : : struct dir24_8_tbl *dp;
562 : : uint64_t def_nh;
563 : : uint32_t num_tbl8;
564 : : enum rte_fib_dir24_8_nh_sz nh_sz;
565 : :
566 [ + - ]: 8 : if ((name == NULL) || (fib_conf == NULL) ||
567 : 8 : (fib_conf->dir24_8.nh_sz < RTE_FIB_DIR24_8_1B) ||
568 [ + + + - ]: 8 : (fib_conf->dir24_8.nh_sz > RTE_FIB_DIR24_8_8B) ||
569 : 7 : (fib_conf->dir24_8.num_tbl8 >
570 [ + - + + ]: 7 : get_max_nh(fib_conf->dir24_8.nh_sz)) ||
571 : 6 : (fib_conf->dir24_8.num_tbl8 == 0) ||
572 [ - + ]: 6 : (fib_conf->default_nh >
573 : : get_max_nh(fib_conf->dir24_8.nh_sz))) {
574 : 2 : rte_errno = EINVAL;
575 : 2 : return NULL;
576 : : }
577 : :
578 : : def_nh = fib_conf->default_nh;
579 : : nh_sz = fib_conf->dir24_8.nh_sz;
580 : 6 : num_tbl8 = RTE_ALIGN_CEIL(fib_conf->dir24_8.num_tbl8,
581 : : BITMAP_SLAB_BIT_SIZE);
582 : :
583 : : snprintf(mem_name, sizeof(mem_name), "DP_%s", name);
584 : 6 : dp = rte_zmalloc_socket(name, sizeof(struct dir24_8_tbl) +
585 : 6 : DIR24_8_TBL24_NUM_ENT * (1 << nh_sz) + sizeof(uint32_t),
586 : : RTE_CACHE_LINE_SIZE, socket_id);
587 [ - + ]: 6 : if (dp == NULL) {
588 : 0 : rte_errno = ENOMEM;
589 : 0 : return NULL;
590 : : }
591 : :
592 : : /* Init table with default value */
593 : 6 : write_to_fib(dp->tbl24, (def_nh << 1), nh_sz, 1 << 24);
594 : :
595 : : snprintf(mem_name, sizeof(mem_name), "TBL8_%p", dp);
596 : 6 : uint64_t tbl8_sz = DIR24_8_TBL8_GRP_NUM_ENT * (1ULL << nh_sz) *
597 : 6 : (num_tbl8 + 1);
598 : 6 : dp->tbl8 = rte_zmalloc_socket(mem_name, tbl8_sz,
599 : : RTE_CACHE_LINE_SIZE, socket_id);
600 [ - + ]: 6 : if (dp->tbl8 == NULL) {
601 : 0 : rte_errno = ENOMEM;
602 : 0 : rte_free(dp);
603 : 0 : return NULL;
604 : : }
605 : 6 : dp->def_nh = def_nh;
606 : 6 : dp->nh_sz = nh_sz;
607 : 6 : dp->number_tbl8s = num_tbl8;
608 : :
609 : : snprintf(mem_name, sizeof(mem_name), "TBL8_idxes_%p", dp);
610 : 12 : dp->tbl8_idxes = rte_zmalloc_socket(mem_name,
611 : 6 : RTE_ALIGN_CEIL(dp->number_tbl8s, 64) >> 3,
612 : : RTE_CACHE_LINE_SIZE, socket_id);
613 [ - + ]: 6 : if (dp->tbl8_idxes == NULL) {
614 : 0 : rte_errno = ENOMEM;
615 : 0 : rte_free(dp->tbl8);
616 : 0 : rte_free(dp);
617 : 0 : return NULL;
618 : : }
619 : :
620 : : return dp;
621 : : }
622 : :
623 : : void
624 : 6 : dir24_8_free(void *p)
625 : : {
626 : : struct dir24_8_tbl *dp = (struct dir24_8_tbl *)p;
627 : :
628 : 6 : rte_rcu_qsbr_dq_delete(dp->dq);
629 : 6 : rte_free(dp->tbl8_idxes);
630 : 6 : rte_free(dp->tbl8);
631 : 6 : rte_free(dp);
632 : 6 : }
633 : :
634 : : int
635 : 5 : dir24_8_rcu_qsbr_add(struct dir24_8_tbl *dp, struct rte_fib_rcu_config *cfg,
636 : : const char *name)
637 : : {
638 : 5 : struct rte_rcu_qsbr_dq_parameters params = {0};
639 : : char rcu_dq_name[RTE_RCU_QSBR_DQ_NAMESIZE];
640 : :
641 [ + + ]: 5 : if (dp == NULL || cfg == NULL)
642 : : return -EINVAL;
643 : :
644 [ + + ]: 4 : if (dp->v != NULL)
645 : : return -EEXIST;
646 : :
647 [ + + ]: 3 : if (cfg->mode == RTE_FIB_QSBR_MODE_SYNC) {
648 : : /* No other things to do. */
649 [ + + ]: 2 : } else if (cfg->mode == RTE_FIB_QSBR_MODE_DQ) {
650 : : /* Init QSBR defer queue. */
651 : : snprintf(rcu_dq_name, sizeof(rcu_dq_name),
652 : : "FIB_RCU_%s", name);
653 : 1 : params.name = rcu_dq_name;
654 : 1 : params.size = cfg->dq_size;
655 [ + - ]: 1 : if (params.size == 0)
656 : 1 : params.size = RTE_FIB_RCU_DQ_RECLAIM_SZ;
657 : 1 : params.trigger_reclaim_limit = cfg->reclaim_thd;
658 : 1 : params.max_reclaim_size = cfg->reclaim_max;
659 [ + - ]: 1 : if (params.max_reclaim_size == 0)
660 : 1 : params.max_reclaim_size = RTE_FIB_RCU_DQ_RECLAIM_MAX;
661 : 1 : params.esize = sizeof(uint64_t);
662 : 1 : params.free_fn = __rcu_qsbr_free_resource;
663 : 1 : params.p = dp;
664 : 1 : params.v = cfg->v;
665 : 1 : dp->dq = rte_rcu_qsbr_dq_create(¶ms);
666 [ - + ]: 1 : if (dp->dq == NULL) {
667 : 0 : FIB_LOG(ERR, "LPM defer queue creation failed");
668 : 0 : return -rte_errno;
669 : : }
670 : : } else {
671 : : return -EINVAL;
672 : : }
673 : :
674 : 2 : dp->rcu_mode = cfg->mode;
675 : 2 : dp->v = cfg->v;
676 : :
677 : 2 : return 0;
678 : : }
|