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 : :
14 : : #include <rte_rib.h>
15 : : #include <rte_fib.h>
16 : : #include "dir24_8.h"
17 : :
18 : : #ifdef CC_DIR24_8_AVX512_SUPPORT
19 : :
20 : : #include "dir24_8_avx512.h"
21 : :
22 : : #endif /* CC_DIR24_8_AVX512_SUPPORT */
23 : :
24 : : #define DIR24_8_NAMESIZE 64
25 : :
26 : : #define ROUNDUP(x, y) RTE_ALIGN_CEIL(x, (1 << (32 - y)))
27 : :
28 : : static inline rte_fib_lookup_fn_t
29 : : get_scalar_fn(enum rte_fib_dir24_8_nh_sz nh_sz)
30 : : {
31 [ - - - - : 4 : switch (nh_sz) {
- + + + -
+ ]
32 : : case RTE_FIB_DIR24_8_1B:
33 : : return dir24_8_lookup_bulk_1b;
34 : 1 : case RTE_FIB_DIR24_8_2B:
35 : 1 : return dir24_8_lookup_bulk_2b;
36 : 1 : case RTE_FIB_DIR24_8_4B:
37 : 1 : return dir24_8_lookup_bulk_4b;
38 : 1 : case RTE_FIB_DIR24_8_8B:
39 : 1 : return dir24_8_lookup_bulk_8b;
40 : 0 : default:
41 : 0 : return NULL;
42 : : }
43 : : }
44 : :
45 : : static inline rte_fib_lookup_fn_t
46 : : get_scalar_fn_inlined(enum rte_fib_dir24_8_nh_sz nh_sz)
47 : : {
48 [ # # # # : 0 : switch (nh_sz) {
# ]
49 : : case RTE_FIB_DIR24_8_1B:
50 : : return dir24_8_lookup_bulk_0;
51 : 0 : case RTE_FIB_DIR24_8_2B:
52 : 0 : return dir24_8_lookup_bulk_1;
53 : 0 : case RTE_FIB_DIR24_8_4B:
54 : 0 : return dir24_8_lookup_bulk_2;
55 : 0 : case RTE_FIB_DIR24_8_8B:
56 : 0 : return dir24_8_lookup_bulk_3;
57 : 0 : default:
58 : 0 : return NULL;
59 : : }
60 : : }
61 : :
62 : : static inline rte_fib_lookup_fn_t
63 : 4 : get_vector_fn(enum rte_fib_dir24_8_nh_sz nh_sz)
64 : : {
65 : : #ifdef CC_DIR24_8_AVX512_SUPPORT
66 [ + - + - ]: 8 : if ((rte_cpu_get_flag_enabled(RTE_CPUFLAG_AVX512F) <= 0) ||
67 : 4 : (rte_vect_get_max_simd_bitwidth() < RTE_VECT_SIMD_512))
68 : 4 : return NULL;
69 : :
70 [ # # # # : 0 : switch (nh_sz) {
# ]
71 : : case RTE_FIB_DIR24_8_1B:
72 : : return rte_dir24_8_vec_lookup_bulk_1b;
73 : 0 : case RTE_FIB_DIR24_8_2B:
74 : 0 : return rte_dir24_8_vec_lookup_bulk_2b;
75 : 0 : case RTE_FIB_DIR24_8_4B:
76 : 0 : return rte_dir24_8_vec_lookup_bulk_4b;
77 : 0 : case RTE_FIB_DIR24_8_8B:
78 : 0 : return rte_dir24_8_vec_lookup_bulk_8b;
79 : 0 : default:
80 : 0 : return NULL;
81 : : }
82 : : #else
83 : : RTE_SET_USED(nh_sz);
84 : : #endif
85 : : return NULL;
86 : : }
87 : :
88 : : rte_fib_lookup_fn_t
89 : 4 : dir24_8_get_lookup_fn(void *p, enum rte_fib_lookup_type type)
90 : : {
91 : : enum rte_fib_dir24_8_nh_sz nh_sz;
92 : : rte_fib_lookup_fn_t ret_fn;
93 : : struct dir24_8_tbl *dp = p;
94 : :
95 [ + - ]: 4 : if (dp == NULL)
96 : : return NULL;
97 : :
98 : 4 : nh_sz = dp->nh_sz;
99 : :
100 [ - - - + : 4 : switch (type) {
- - ]
101 : : case RTE_FIB_LOOKUP_DIR24_8_SCALAR_MACRO:
102 : : return get_scalar_fn(nh_sz);
103 : : case RTE_FIB_LOOKUP_DIR24_8_SCALAR_INLINE:
104 : : return get_scalar_fn_inlined(nh_sz);
105 : : case RTE_FIB_LOOKUP_DIR24_8_SCALAR_UNI:
106 : : return dir24_8_lookup_bulk_uni;
107 : 0 : case RTE_FIB_LOOKUP_DIR24_8_VECTOR_AVX512:
108 : 0 : return get_vector_fn(nh_sz);
109 : 4 : case RTE_FIB_LOOKUP_DEFAULT:
110 : 4 : ret_fn = get_vector_fn(nh_sz);
111 [ + - ]: 4 : return (ret_fn != NULL) ? ret_fn : get_scalar_fn(nh_sz);
112 : 0 : default:
113 : 0 : return NULL;
114 : : }
115 : :
116 : : return NULL;
117 : : }
118 : :
119 : : static void
120 : 540 : write_to_fib(void *ptr, uint64_t val, enum rte_fib_dir24_8_nh_sz size, int n)
121 : : {
122 : : int i;
123 : : uint8_t *ptr8 = (uint8_t *)ptr;
124 : : uint16_t *ptr16 = (uint16_t *)ptr;
125 : : uint32_t *ptr32 = (uint32_t *)ptr;
126 : : uint64_t *ptr64 = (uint64_t *)ptr;
127 : :
128 [ + + + + : 540 : switch (size) {
- ]
129 : : case RTE_FIB_DIR24_8_1B:
130 [ + + ]: 67110531 : for (i = 0; i < n; i++)
131 : 67110396 : ptr8[i] = (uint8_t)val;
132 : : break;
133 : : case RTE_FIB_DIR24_8_2B:
134 [ + + ]: 67110531 : for (i = 0; i < n; i++)
135 : 67110396 : ptr16[i] = (uint16_t)val;
136 : : break;
137 : : case RTE_FIB_DIR24_8_4B:
138 [ + + ]: 67110531 : for (i = 0; i < n; i++)
139 : 67110396 : ptr32[i] = (uint32_t)val;
140 : : break;
141 : : case RTE_FIB_DIR24_8_8B:
142 [ + + ]: 67110531 : for (i = 0; i < n; i++)
143 : 67110396 : ptr64[i] = (uint64_t)val;
144 : : break;
145 : : }
146 : 540 : }
147 : :
148 : : static int
149 : 8 : tbl8_get_idx(struct dir24_8_tbl *dp)
150 : : {
151 : : uint32_t i;
152 : : int bit_idx;
153 : :
154 [ + - ]: 8 : for (i = 0; (i < (dp->number_tbl8s >> BITMAP_SLAB_BIT_SIZE_LOG2)) &&
155 [ - + ]: 8 : (dp->tbl8_idxes[i] == UINT64_MAX); i++)
156 : : ;
157 [ + - ]: 8 : if (i < (dp->number_tbl8s >> BITMAP_SLAB_BIT_SIZE_LOG2)) {
158 : 8 : bit_idx = rte_ctz64(~dp->tbl8_idxes[i]);
159 : 8 : dp->tbl8_idxes[i] |= (1ULL << bit_idx);
160 : 8 : return (i << BITMAP_SLAB_BIT_SIZE_LOG2) + bit_idx;
161 : : }
162 : : return -ENOSPC;
163 : : }
164 : :
165 : : static inline void
166 : : tbl8_free_idx(struct dir24_8_tbl *dp, int idx)
167 : : {
168 : 8 : dp->tbl8_idxes[idx >> BITMAP_SLAB_BIT_SIZE_LOG2] &=
169 : 8 : ~(1ULL << (idx & BITMAP_SLAB_BITMASK));
170 : : }
171 : :
172 : : static int
173 : 8 : tbl8_alloc(struct dir24_8_tbl *dp, uint64_t nh)
174 : : {
175 : : int64_t tbl8_idx;
176 : : uint8_t *tbl8_ptr;
177 : :
178 : 8 : tbl8_idx = tbl8_get_idx(dp);
179 [ + - ]: 8 : if (tbl8_idx < 0)
180 : : return tbl8_idx;
181 : 8 : tbl8_ptr = (uint8_t *)dp->tbl8 +
182 : 8 : ((tbl8_idx * DIR24_8_TBL8_GRP_NUM_ENT) <<
183 : 8 : dp->nh_sz);
184 : : /*Init tbl8 entries with nexthop from tbl24*/
185 : 8 : write_to_fib((void *)tbl8_ptr, nh|
186 : : DIR24_8_EXT_ENT, dp->nh_sz,
187 : : DIR24_8_TBL8_GRP_NUM_ENT);
188 : 8 : dp->cur_tbl8s++;
189 : 8 : return tbl8_idx;
190 : : }
191 : :
192 : : static void
193 : 136 : tbl8_recycle(struct dir24_8_tbl *dp, uint32_t ip, uint64_t tbl8_idx)
194 : : {
195 : : uint32_t i;
196 : : uint64_t nh;
197 : : uint8_t *ptr8;
198 : : uint16_t *ptr16;
199 : : uint32_t *ptr32;
200 : : uint64_t *ptr64;
201 : :
202 [ + + + + : 136 : switch (dp->nh_sz) {
- ]
203 : 34 : case RTE_FIB_DIR24_8_1B:
204 : 34 : ptr8 = &((uint8_t *)dp->tbl8)[tbl8_idx *
205 : : DIR24_8_TBL8_GRP_NUM_ENT];
206 : 34 : nh = *ptr8;
207 [ + + ]: 1038 : for (i = 1; i < DIR24_8_TBL8_GRP_NUM_ENT; i++) {
208 [ + + ]: 1036 : if (nh != ptr8[i])
209 : : return;
210 : : }
211 : 2 : ((uint8_t *)dp->tbl24)[ip >> 8] =
212 : 2 : nh & ~DIR24_8_EXT_ENT;
213 [ + + ]: 514 : for (i = 0; i < DIR24_8_TBL8_GRP_NUM_ENT; i++)
214 : 512 : ptr8[i] = 0;
215 : : break;
216 : 34 : case RTE_FIB_DIR24_8_2B:
217 : 34 : ptr16 = &((uint16_t *)dp->tbl8)[tbl8_idx *
218 : : DIR24_8_TBL8_GRP_NUM_ENT];
219 : 34 : nh = *ptr16;
220 [ + + ]: 1038 : for (i = 1; i < DIR24_8_TBL8_GRP_NUM_ENT; i++) {
221 [ + + ]: 1036 : if (nh != ptr16[i])
222 : : return;
223 : : }
224 : 2 : ((uint16_t *)dp->tbl24)[ip >> 8] =
225 : 2 : nh & ~DIR24_8_EXT_ENT;
226 [ + + ]: 514 : for (i = 0; i < DIR24_8_TBL8_GRP_NUM_ENT; i++)
227 : 512 : ptr16[i] = 0;
228 : : break;
229 : 34 : case RTE_FIB_DIR24_8_4B:
230 : 34 : ptr32 = &((uint32_t *)dp->tbl8)[tbl8_idx *
231 : : DIR24_8_TBL8_GRP_NUM_ENT];
232 : 34 : nh = *ptr32;
233 [ + + ]: 1038 : for (i = 1; i < DIR24_8_TBL8_GRP_NUM_ENT; i++) {
234 [ + + ]: 1036 : if (nh != ptr32[i])
235 : : return;
236 : : }
237 : 2 : ((uint32_t *)dp->tbl24)[ip >> 8] =
238 : 2 : nh & ~DIR24_8_EXT_ENT;
239 [ + + ]: 514 : for (i = 0; i < DIR24_8_TBL8_GRP_NUM_ENT; i++)
240 : 512 : ptr32[i] = 0;
241 : : break;
242 : 34 : case RTE_FIB_DIR24_8_8B:
243 : 34 : ptr64 = &((uint64_t *)dp->tbl8)[tbl8_idx *
244 : : DIR24_8_TBL8_GRP_NUM_ENT];
245 : 34 : nh = *ptr64;
246 [ + + ]: 1038 : for (i = 1; i < DIR24_8_TBL8_GRP_NUM_ENT; i++) {
247 [ + + ]: 1036 : if (nh != ptr64[i])
248 : : return;
249 : : }
250 : 2 : ((uint64_t *)dp->tbl24)[ip >> 8] =
251 : 2 : nh & ~DIR24_8_EXT_ENT;
252 [ + + ]: 514 : for (i = 0; i < DIR24_8_TBL8_GRP_NUM_ENT; i++)
253 : 512 : ptr64[i] = 0;
254 : : break;
255 : : }
256 : 8 : tbl8_free_idx(dp, tbl8_idx);
257 : 8 : dp->cur_tbl8s--;
258 : : }
259 : :
260 : : static int
261 : 512 : install_to_fib(struct dir24_8_tbl *dp, uint32_t ledge, uint32_t redge,
262 : : uint64_t next_hop)
263 : : {
264 : : uint64_t tbl24_tmp;
265 : : int tbl8_idx;
266 : : int tmp_tbl8_idx;
267 : : uint8_t *tbl8_ptr;
268 : : uint32_t len;
269 : :
270 [ + - ]: 512 : len = ((ledge == 0) && (redge == 0)) ? 1 << 24 :
271 : 512 : ((redge & DIR24_8_TBL24_MASK) - ROUNDUP(ledge, 24)) >> 8;
272 : :
273 [ + + - + ]: 512 : if (((ledge >> 8) != (redge >> 8)) || (len == 1 << 24)) {
274 [ + + ]: 384 : if ((ROUNDUP(ledge, 24) - ledge) != 0) {
275 [ - + ]: 8 : tbl24_tmp = get_tbl24(dp, ledge, dp->nh_sz);
276 [ - + ]: 8 : if ((tbl24_tmp & DIR24_8_EXT_ENT) !=
277 : : DIR24_8_EXT_ENT) {
278 : : /**
279 : : * Make sure there is space for two TBL8.
280 : : * This is necessary when installing range that
281 : : * needs tbl8 for ledge and redge.
282 : : */
283 : 0 : tbl8_idx = tbl8_alloc(dp, tbl24_tmp);
284 : 0 : tmp_tbl8_idx = tbl8_get_idx(dp);
285 [ # # ]: 0 : if (tbl8_idx < 0)
286 : : return -ENOSPC;
287 [ # # ]: 0 : else if (tmp_tbl8_idx < 0) {
288 : : tbl8_free_idx(dp, tbl8_idx);
289 : 0 : return -ENOSPC;
290 : : }
291 : : tbl8_free_idx(dp, tmp_tbl8_idx);
292 : : /*update dir24 entry with tbl8 index*/
293 : 0 : write_to_fib(get_tbl24_p(dp, ledge,
294 : 0 : dp->nh_sz), (tbl8_idx << 1)|
295 : : DIR24_8_EXT_ENT,
296 : : dp->nh_sz, 1);
297 : : } else
298 : 8 : tbl8_idx = tbl24_tmp >> 1;
299 : 8 : tbl8_ptr = (uint8_t *)dp->tbl8 +
300 : 8 : (((tbl8_idx * DIR24_8_TBL8_GRP_NUM_ENT) +
301 : 8 : (ledge & ~DIR24_8_TBL24_MASK)) <<
302 : 8 : dp->nh_sz);
303 : : /*update tbl8 with new next hop*/
304 : 8 : write_to_fib((void *)tbl8_ptr, (next_hop << 1)|
305 : : DIR24_8_EXT_ENT,
306 : 8 : dp->nh_sz, ROUNDUP(ledge, 24) - ledge);
307 : 8 : tbl8_recycle(dp, ledge, tbl8_idx);
308 : : }
309 : 384 : write_to_fib(get_tbl24_p(dp, ROUNDUP(ledge, 24), dp->nh_sz),
310 : : next_hop << 1, dp->nh_sz, len);
311 [ - + ]: 384 : if (redge & ~DIR24_8_TBL24_MASK) {
312 [ # # ]: 0 : tbl24_tmp = get_tbl24(dp, redge, dp->nh_sz);
313 [ # # ]: 0 : if ((tbl24_tmp & DIR24_8_EXT_ENT) !=
314 : : DIR24_8_EXT_ENT) {
315 : 0 : tbl8_idx = tbl8_alloc(dp, tbl24_tmp);
316 [ # # ]: 0 : if (tbl8_idx < 0)
317 : : return -ENOSPC;
318 : : /*update dir24 entry with tbl8 index*/
319 : 0 : write_to_fib(get_tbl24_p(dp, redge,
320 : 0 : dp->nh_sz), (tbl8_idx << 1)|
321 : : DIR24_8_EXT_ENT,
322 : : dp->nh_sz, 1);
323 : : } else
324 : 0 : tbl8_idx = tbl24_tmp >> 1;
325 : 0 : tbl8_ptr = (uint8_t *)dp->tbl8 +
326 : 0 : ((tbl8_idx * DIR24_8_TBL8_GRP_NUM_ENT) <<
327 : 0 : dp->nh_sz);
328 : : /*update tbl8 with new next hop*/
329 : 0 : write_to_fib((void *)tbl8_ptr, (next_hop << 1)|
330 : : DIR24_8_EXT_ENT,
331 : 0 : dp->nh_sz, redge & ~DIR24_8_TBL24_MASK);
332 : 0 : tbl8_recycle(dp, redge, tbl8_idx);
333 : : }
334 [ + - ]: 128 : } else if ((redge - ledge) != 0) {
335 [ + + ]: 128 : tbl24_tmp = get_tbl24(dp, ledge, dp->nh_sz);
336 [ + + ]: 128 : if ((tbl24_tmp & DIR24_8_EXT_ENT) !=
337 : : DIR24_8_EXT_ENT) {
338 : 8 : tbl8_idx = tbl8_alloc(dp, tbl24_tmp);
339 [ + - ]: 8 : if (tbl8_idx < 0)
340 : : return -ENOSPC;
341 : : /*update dir24 entry with tbl8 index*/
342 : 8 : write_to_fib(get_tbl24_p(dp, ledge, dp->nh_sz),
343 : 8 : (tbl8_idx << 1)|
344 : : DIR24_8_EXT_ENT,
345 : : dp->nh_sz, 1);
346 : : } else
347 : 120 : tbl8_idx = tbl24_tmp >> 1;
348 : 128 : tbl8_ptr = (uint8_t *)dp->tbl8 +
349 : 128 : (((tbl8_idx * DIR24_8_TBL8_GRP_NUM_ENT) +
350 : 128 : (ledge & ~DIR24_8_TBL24_MASK)) <<
351 : 128 : dp->nh_sz);
352 : : /*update tbl8 with new next hop*/
353 : 128 : write_to_fib((void *)tbl8_ptr, (next_hop << 1)|
354 : : DIR24_8_EXT_ENT,
355 : 128 : dp->nh_sz, redge - ledge);
356 : 128 : tbl8_recycle(dp, ledge, tbl8_idx);
357 : : }
358 : : return 0;
359 : : }
360 : :
361 : : static int
362 : 512 : modify_fib(struct dir24_8_tbl *dp, struct rte_rib *rib, uint32_t ip,
363 : : uint8_t depth, uint64_t next_hop)
364 : : {
365 : : struct rte_rib_node *tmp = NULL;
366 : : uint32_t ledge, redge, tmp_ip;
367 : : int ret;
368 : : uint8_t tmp_depth;
369 : :
370 : : ledge = ip;
371 : : do {
372 : 760 : tmp = rte_rib_get_nxt(rib, ip, depth, tmp,
373 : : RTE_RIB_GET_NXT_COVER);
374 [ + + ]: 760 : if (tmp != NULL) {
375 : 248 : rte_rib_get_depth(tmp, &tmp_depth);
376 [ - + ]: 248 : if (tmp_depth == depth)
377 : 0 : continue;
378 : 248 : rte_rib_get_ip(tmp, &tmp_ip);
379 [ + - ]: 248 : redge = tmp_ip & rte_rib_depth_to_mask(tmp_depth);
380 [ + - ]: 248 : if (ledge == redge) {
381 : 248 : ledge = redge +
382 : 248 : (uint32_t)(1ULL << (32 - tmp_depth));
383 : 248 : continue;
384 : : }
385 : 0 : ret = install_to_fib(dp, ledge, redge,
386 : : next_hop);
387 [ # # ]: 0 : if (ret != 0)
388 : 0 : return ret;
389 : 0 : ledge = redge +
390 : 0 : (uint32_t)(1ULL << (32 - tmp_depth));
391 : : /*
392 : : * we got to the end of address space
393 : : * and wrapped around
394 : : */
395 [ # # ]: 0 : if (ledge == 0)
396 : : break;
397 : : } else {
398 : 512 : redge = ip + (uint32_t)(1ULL << (32 - depth));
399 [ + - ]: 512 : if (ledge == redge && ledge != 0)
400 : : break;
401 : 512 : ret = install_to_fib(dp, ledge, redge,
402 : : next_hop);
403 [ - + ]: 512 : if (ret != 0)
404 : 0 : return ret;
405 : : }
406 [ + + ]: 760 : } while (tmp);
407 : :
408 : : return 0;
409 : : }
410 : :
411 : : int
412 : 512 : dir24_8_modify(struct rte_fib *fib, uint32_t ip, uint8_t depth,
413 : : uint64_t next_hop, int op)
414 : : {
415 : : struct dir24_8_tbl *dp;
416 : : struct rte_rib *rib;
417 : : struct rte_rib_node *tmp = NULL;
418 : : struct rte_rib_node *node;
419 : : struct rte_rib_node *parent;
420 : : int ret = 0;
421 : : uint64_t par_nh, node_nh;
422 : :
423 [ + - ]: 512 : if ((fib == NULL) || (depth > RTE_FIB_MAXDEPTH))
424 : : return -EINVAL;
425 : :
426 : 512 : dp = rte_fib_get_dp(fib);
427 : 512 : rib = rte_fib_get_rib(fib);
428 : : RTE_ASSERT((dp != NULL) && (rib != NULL));
429 : :
430 [ + - ]: 512 : if (next_hop > get_max_nh(dp->nh_sz))
431 : : return -EINVAL;
432 : :
433 : 512 : ip &= rte_rib_depth_to_mask(depth);
434 : :
435 : 512 : node = rte_rib_lookup_exact(rib, ip, depth);
436 [ + + - ]: 512 : switch (op) {
437 : 256 : case RTE_FIB_ADD:
438 [ - + ]: 256 : if (node != NULL) {
439 : 0 : rte_rib_get_nh(node, &node_nh);
440 [ # # ]: 0 : if (node_nh == next_hop)
441 : : return 0;
442 : 0 : ret = modify_fib(dp, rib, ip, depth, next_hop);
443 [ # # ]: 0 : if (ret == 0)
444 : 0 : rte_rib_set_nh(node, next_hop);
445 : 0 : return 0;
446 : : }
447 [ + + ]: 256 : if (depth > 24) {
448 : 64 : tmp = rte_rib_get_nxt(rib, ip, 24, NULL,
449 : : RTE_RIB_GET_NXT_COVER);
450 [ + + ]: 64 : if ((tmp == NULL) &&
451 [ + - ]: 8 : (dp->rsvd_tbl8s >= dp->number_tbl8s))
452 : : return -ENOSPC;
453 : :
454 : : }
455 : 256 : node = rte_rib_insert(rib, ip, depth);
456 [ - + ]: 256 : if (node == NULL)
457 : 0 : return -rte_errno;
458 : 256 : rte_rib_set_nh(node, next_hop);
459 : 256 : parent = rte_rib_lookup_parent(node);
460 [ + + ]: 256 : if (parent != NULL) {
461 : 124 : rte_rib_get_nh(parent, &par_nh);
462 [ + - ]: 124 : if (par_nh == next_hop)
463 : : return 0;
464 : : }
465 : 256 : ret = modify_fib(dp, rib, ip, depth, next_hop);
466 [ - + ]: 256 : if (ret != 0) {
467 : 0 : rte_rib_remove(rib, ip, depth);
468 : 0 : return ret;
469 : : }
470 [ + + ]: 256 : if ((depth > 24) && (tmp == NULL))
471 : 8 : dp->rsvd_tbl8s++;
472 : : return 0;
473 : 256 : case RTE_FIB_DEL:
474 [ + - ]: 256 : if (node == NULL)
475 : : return -ENOENT;
476 : :
477 : 256 : parent = rte_rib_lookup_parent(node);
478 [ + + ]: 256 : if (parent != NULL) {
479 : 124 : rte_rib_get_nh(parent, &par_nh);
480 : 124 : rte_rib_get_nh(node, &node_nh);
481 [ + - ]: 124 : if (par_nh != node_nh)
482 : 124 : ret = modify_fib(dp, rib, ip, depth, par_nh);
483 : : } else
484 : 132 : ret = modify_fib(dp, rib, ip, depth, dp->def_nh);
485 [ + - ]: 256 : if (ret == 0) {
486 : 256 : rte_rib_remove(rib, ip, depth);
487 [ + + ]: 256 : if (depth > 24) {
488 : 64 : tmp = rte_rib_get_nxt(rib, ip, 24, NULL,
489 : : RTE_RIB_GET_NXT_COVER);
490 [ + + ]: 64 : if (tmp == NULL)
491 : 8 : dp->rsvd_tbl8s--;
492 : : }
493 : : }
494 : : return ret;
495 : : default:
496 : : break;
497 : : }
498 : : return -EINVAL;
499 : : }
500 : :
501 : : void *
502 : 6 : dir24_8_create(const char *name, int socket_id, struct rte_fib_conf *fib_conf)
503 : : {
504 : : char mem_name[DIR24_8_NAMESIZE];
505 : : struct dir24_8_tbl *dp;
506 : : uint64_t def_nh;
507 : : uint32_t num_tbl8;
508 : : enum rte_fib_dir24_8_nh_sz nh_sz;
509 : :
510 [ + - ]: 6 : if ((name == NULL) || (fib_conf == NULL) ||
511 : 6 : (fib_conf->dir24_8.nh_sz < RTE_FIB_DIR24_8_1B) ||
512 [ + + + - ]: 6 : (fib_conf->dir24_8.nh_sz > RTE_FIB_DIR24_8_8B) ||
513 : 5 : (fib_conf->dir24_8.num_tbl8 >
514 [ + - + + ]: 5 : get_max_nh(fib_conf->dir24_8.nh_sz)) ||
515 : 4 : (fib_conf->dir24_8.num_tbl8 == 0) ||
516 [ - + ]: 4 : (fib_conf->default_nh >
517 : : get_max_nh(fib_conf->dir24_8.nh_sz))) {
518 : 2 : rte_errno = EINVAL;
519 : 2 : return NULL;
520 : : }
521 : :
522 : : def_nh = fib_conf->default_nh;
523 : : nh_sz = fib_conf->dir24_8.nh_sz;
524 : 4 : num_tbl8 = RTE_ALIGN_CEIL(fib_conf->dir24_8.num_tbl8,
525 : : BITMAP_SLAB_BIT_SIZE);
526 : :
527 : : snprintf(mem_name, sizeof(mem_name), "DP_%s", name);
528 : 4 : dp = rte_zmalloc_socket(name, sizeof(struct dir24_8_tbl) +
529 : 4 : DIR24_8_TBL24_NUM_ENT * (1 << nh_sz), RTE_CACHE_LINE_SIZE,
530 : : socket_id);
531 [ - + ]: 4 : if (dp == NULL) {
532 : 0 : rte_errno = ENOMEM;
533 : 0 : return NULL;
534 : : }
535 : :
536 : : /* Init table with default value */
537 : 4 : write_to_fib(dp->tbl24, (def_nh << 1), nh_sz, 1 << 24);
538 : :
539 : : snprintf(mem_name, sizeof(mem_name), "TBL8_%p", dp);
540 : 4 : uint64_t tbl8_sz = DIR24_8_TBL8_GRP_NUM_ENT * (1ULL << nh_sz) *
541 : 4 : (num_tbl8 + 1);
542 : 4 : dp->tbl8 = rte_zmalloc_socket(mem_name, tbl8_sz,
543 : : RTE_CACHE_LINE_SIZE, socket_id);
544 [ - + ]: 4 : if (dp->tbl8 == NULL) {
545 : 0 : rte_errno = ENOMEM;
546 : 0 : rte_free(dp);
547 : 0 : return NULL;
548 : : }
549 : 4 : dp->def_nh = def_nh;
550 : 4 : dp->nh_sz = nh_sz;
551 : 4 : dp->number_tbl8s = num_tbl8;
552 : :
553 : : snprintf(mem_name, sizeof(mem_name), "TBL8_idxes_%p", dp);
554 : 8 : dp->tbl8_idxes = rte_zmalloc_socket(mem_name,
555 : 4 : RTE_ALIGN_CEIL(dp->number_tbl8s, 64) >> 3,
556 : : RTE_CACHE_LINE_SIZE, socket_id);
557 [ - + ]: 4 : if (dp->tbl8_idxes == NULL) {
558 : 0 : rte_errno = ENOMEM;
559 : 0 : rte_free(dp->tbl8);
560 : 0 : rte_free(dp);
561 : 0 : return NULL;
562 : : }
563 : :
564 : : return dp;
565 : : }
566 : :
567 : : void
568 : 4 : dir24_8_free(void *p)
569 : : {
570 : : struct dir24_8_tbl *dp = (struct dir24_8_tbl *)p;
571 : :
572 : 4 : rte_free(dp->tbl8_idxes);
573 : 4 : rte_free(dp->tbl8);
574 : 4 : rte_free(dp);
575 : 4 : }
|