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 <stdbool.h>
7 : : #include <stdint.h>
8 : : #include <sys/queue.h>
9 : :
10 : : #include <eal_export.h>
11 : : #include <rte_eal_memconfig.h>
12 : : #include <rte_errno.h>
13 : : #include <rte_log.h>
14 : : #include <rte_malloc.h>
15 : : #include <rte_mempool.h>
16 : : #include <rte_string_fns.h>
17 : : #include <rte_tailq.h>
18 : :
19 : : #include <rte_rib6.h>
20 : :
21 : : #include "rib_log.h"
22 : : #include "rib6_internal.h"
23 : :
24 : : #define RTE_RIB_VALID_NODE 1
25 : : /* Maximum length of a RIB6 name. */
26 : : #define RTE_RIB6_NAMESIZE 64
27 : :
28 : : TAILQ_HEAD(rte_rib6_list, rte_tailq_entry);
29 : : static struct rte_tailq_elem rte_rib6_tailq = {
30 : : .name = "RTE_RIB6",
31 : : };
32 [ - + ]: 303 : EAL_REGISTER_TAILQ(rte_rib6_tailq)
33 : :
34 : : struct rte_rib6_node {
35 : : struct rte_rib6_node *left;
36 : : struct rte_rib6_node *right;
37 : : struct rte_rib6_node *parent;
38 : : uint64_t nh;
39 : : struct rte_ipv6_addr ip;
40 : : uint8_t depth;
41 : : uint8_t flag;
42 : : uint64_t ext[];
43 : : };
44 : :
45 : : struct rte_rib6 {
46 : : char name[RTE_RIB6_NAMESIZE];
47 : : struct rte_rib6_node *tree;
48 : : struct rte_mempool *node_pool;
49 : : uint32_t cur_nodes;
50 : : uint32_t cur_routes;
51 : : int max_nodes;
52 : : };
53 : :
54 : : static inline bool
55 : : is_valid_node(const struct rte_rib6_node *node)
56 : : {
57 : 2136223 : return (node->flag & RTE_RIB_VALID_NODE) == RTE_RIB_VALID_NODE;
58 : : }
59 : :
60 : : static inline bool
61 : : is_right_node(const struct rte_rib6_node *node)
62 : : {
63 : 2964 : return node->parent->right == node;
64 : : }
65 : :
66 : : static inline int
67 : : get_dir(const struct rte_ipv6_addr *ip, uint8_t depth)
68 : : {
69 : : uint8_t index, msk;
70 : :
71 : : /*
72 : : * depth & 127 clamps depth to values that will not
73 : : * read off the end of ip.
74 : : * depth is the number of bits deep into ip to traverse, and
75 : : * is incremented in blocks of 8 (1 byte). This means the last
76 : : * 3 bits are irrelevant to what the index of ip should be.
77 : : */
78 : 2338721 : index = (depth & INT8_MAX) / CHAR_BIT;
79 : :
80 : : /*
81 : : * msk is the bitmask used to extract the bit used to decide the
82 : : * direction of the next step of the binary search.
83 : : */
84 : 2338721 : msk = 1 << (7 - (depth & 7));
85 : :
86 : 2338721 : return (ip->a[index] & msk) != 0;
87 : : }
88 : :
89 : : static inline struct rte_rib6_node *
90 : : get_nxt_node(struct rte_rib6_node *node,
91 : : const struct rte_ipv6_addr *ip)
92 : : {
93 [ + - + - : 2303590 : if (node->depth == RTE_IPV6_MAX_DEPTH)
+ + ]
94 : : return NULL;
95 : :
96 [ + + + + : 2303334 : return (get_dir(ip, node->depth)) ? node->right : node->left;
+ + ]
97 : : }
98 : :
99 : : static struct rte_rib6_node *
100 : 3018 : node_alloc(struct rte_rib6 *rib)
101 : : {
102 : : struct rte_rib6_node *ent;
103 : : int ret;
104 : :
105 [ - + ]: 3018 : ret = rte_mempool_get(rib->node_pool, (void *)&ent);
106 [ + - ]: 3018 : if (unlikely(ret != 0))
107 : : return NULL;
108 : 3018 : ++rib->cur_nodes;
109 : 3018 : return ent;
110 : : }
111 : :
112 : : static void
113 : 3012 : node_free(struct rte_rib6 *rib, struct rte_rib6_node *ent)
114 : : {
115 : 3012 : --rib->cur_nodes;
116 [ - + ]: 3012 : rte_mempool_put(rib->node_pool, ent);
117 : 3012 : }
118 : :
119 : : RTE_EXPORT_SYMBOL(rte_rib6_lookup)
120 : : struct rte_rib6_node *
121 : 66179 : rte_rib6_lookup(struct rte_rib6 *rib,
122 : : const struct rte_ipv6_addr *ip)
123 : : {
124 : : struct rte_rib6_node *cur;
125 : : struct rte_rib6_node *prev = NULL;
126 : :
127 [ - + ]: 66179 : if (unlikely(rib == NULL)) {
128 : 0 : rte_errno = EINVAL;
129 : 0 : return NULL;
130 : : }
131 : 66179 : cur = rib->tree;
132 : :
133 [ + + + + ]: 2179716 : while ((cur != NULL) && rte_ipv6_addr_eq_prefix(ip, &cur->ip, cur->depth)) {
134 [ + - ]: 2113537 : if (is_valid_node(cur))
135 : : prev = cur;
136 : : cur = get_nxt_node(cur, ip);
137 : : }
138 : : return prev;
139 : : }
140 : :
141 : : RTE_EXPORT_SYMBOL(rte_rib6_lookup_parent)
142 : : struct rte_rib6_node *
143 : 4595 : rte_rib6_lookup_parent(struct rte_rib6_node *ent)
144 : : {
145 : : struct rte_rib6_node *tmp;
146 : :
147 [ + - ]: 4595 : if (ent == NULL)
148 : : return NULL;
149 : :
150 : 4595 : tmp = ent->parent;
151 [ + + + + ]: 6588 : while ((tmp != NULL) && (!is_valid_node(tmp)))
152 : 1993 : tmp = tmp->parent;
153 : :
154 : : return tmp;
155 : : }
156 : :
157 : : RTE_EXPORT_SYMBOL(rte_rib6_lookup_exact)
158 : : struct rte_rib6_node *
159 : 10223 : rte_rib6_lookup_exact(struct rte_rib6 *rib,
160 : : const struct rte_ipv6_addr *ip, uint8_t depth)
161 : : {
162 : : struct rte_rib6_node *cur;
163 : : struct rte_ipv6_addr tmp_ip;
164 : :
165 [ + - - + ]: 10223 : if (unlikely(rib == NULL || ip == NULL || depth > RTE_IPV6_MAX_DEPTH)) {
166 : 0 : rte_errno = EINVAL;
167 : 0 : return NULL;
168 : : }
169 : 10223 : cur = rib->tree;
170 : :
171 [ + + ]: 10223 : tmp_ip = *ip;
172 : : rte_ipv6_addr_mask(&tmp_ip, depth);
173 : :
174 [ + + ]: 147481 : while (cur != NULL) {
175 [ + + ]: 144976 : if (rte_ipv6_addr_eq(&cur->ip, &tmp_ip) &&
176 [ + + + - ]: 136841 : (cur->depth == depth) &&
177 : : is_valid_node(cur))
178 : 5109 : return cur;
179 : :
180 [ + + + + ]: 139867 : if (!rte_ipv6_addr_eq_prefix(&tmp_ip, &cur->ip, cur->depth) ||
181 : : (cur->depth >= depth))
182 : : break;
183 : :
184 : : cur = get_nxt_node(cur, &tmp_ip);
185 : : }
186 : :
187 : : return NULL;
188 : : }
189 : :
190 : : /*
191 : : * Traverses on subtree and retrieves more specific routes
192 : : * for a given in args ip/depth prefix
193 : : * last = NULL means the first invocation
194 : : */
195 : : RTE_EXPORT_SYMBOL(rte_rib6_get_nxt)
196 : : struct rte_rib6_node *
197 : 6447 : rte_rib6_get_nxt(struct rte_rib6 *rib,
198 : : const struct rte_ipv6_addr *ip,
199 : : uint8_t depth, struct rte_rib6_node *last, int flag)
200 : : {
201 : : struct rte_rib6_node *tmp, *prev = NULL;
202 : : struct rte_ipv6_addr tmp_ip;
203 : :
204 [ + + - + ]: 6447 : if (unlikely(rib == NULL || ip == NULL || depth > RTE_IPV6_MAX_DEPTH)) {
205 : 21 : rte_errno = EINVAL;
206 : 21 : return NULL;
207 : : }
208 : :
209 : 6426 : tmp_ip = *ip;
210 [ + + ]: 6426 : rte_ipv6_addr_mask(&tmp_ip, depth);
211 : :
212 [ + + ]: 6426 : if (last == NULL) {
213 : 4582 : tmp = rib->tree;
214 [ + - + + ]: 57377 : while ((tmp) && (tmp->depth < depth))
215 : : tmp = get_nxt_node(tmp, &tmp_ip);
216 : : } else {
217 : : tmp = last;
218 [ + + + + : 4185 : while ((tmp->parent != NULL) && (is_right_node(tmp) ||
+ + ]
219 : : (tmp->parent->right == NULL))) {
220 : : tmp = tmp->parent;
221 [ + + ]: 2341 : if (is_valid_node(tmp) &&
222 [ + + ]: 1609 : (rte_ipv6_addr_eq_prefix(&tmp->ip, &tmp_ip, depth) &&
223 [ - + ]: 1458 : (tmp->depth > depth)))
224 : 0 : return tmp;
225 : : }
226 [ + + ]: 1844 : tmp = (tmp->parent != NULL) ? tmp->parent->right : NULL;
227 : : }
228 [ + + ]: 11706 : while (tmp) {
229 [ + + ]: 7124 : if (is_valid_node(tmp) &&
230 [ + + ]: 6738 : (rte_ipv6_addr_eq_prefix(&tmp->ip, &tmp_ip, depth) &&
231 [ + + ]: 6426 : (tmp->depth > depth))) {
232 : : prev = tmp;
233 [ + + ]: 1845 : if (flag == RTE_RIB6_GET_NXT_COVER)
234 : 1844 : return prev;
235 : : }
236 [ + + ]: 5280 : tmp = (tmp->left != NULL) ? tmp->left : tmp->right;
237 : : }
238 : : return prev;
239 : : }
240 : :
241 : : RTE_EXPORT_SYMBOL(rte_rib6_remove)
242 : : void
243 : 2554 : rte_rib6_remove(struct rte_rib6 *rib,
244 : : const struct rte_ipv6_addr *ip, uint8_t depth)
245 : : {
246 : : struct rte_rib6_node *cur, *prev, *child;
247 : :
248 : 2554 : cur = rte_rib6_lookup_exact(rib, ip, depth);
249 [ + - ]: 2554 : if (cur == NULL)
250 : : return;
251 : :
252 : 2554 : --rib->cur_routes;
253 : 2554 : cur->flag &= ~RTE_RIB_VALID_NODE;
254 [ + + ]: 4267 : while (!is_valid_node(cur)) {
255 [ + + + + ]: 3400 : if ((cur->left != NULL) && (cur->right != NULL))
256 : : return;
257 [ + + ]: 3012 : child = (cur->left == NULL) ? cur->right : cur->left;
258 [ + + ]: 3012 : if (child != NULL)
259 : 1326 : child->parent = cur->parent;
260 [ + + ]: 3012 : if (cur->parent == NULL) {
261 : 1299 : rib->tree = child;
262 : 1299 : node_free(rib, cur);
263 : 1299 : return;
264 : : }
265 [ + + ]: 1713 : if (cur->parent->left == cur)
266 : 1319 : cur->parent->left = child;
267 : : else
268 : 394 : cur->parent->right = child;
269 : : prev = cur;
270 : : cur = cur->parent;
271 : 1713 : node_free(rib, prev);
272 : : }
273 : : }
274 : :
275 : : RTE_EXPORT_SYMBOL(rte_rib6_insert)
276 : : struct rte_rib6_node *
277 : 2562 : rte_rib6_insert(struct rte_rib6 *rib,
278 : : const struct rte_ipv6_addr *ip, uint8_t depth)
279 : : {
280 : : struct rte_rib6_node **tmp;
281 : : struct rte_rib6_node *prev = NULL;
282 : : struct rte_rib6_node *new_node = NULL;
283 : : struct rte_rib6_node *common_node = NULL;
284 : : struct rte_ipv6_addr common_prefix;
285 : : struct rte_ipv6_addr tmp_ip;
286 : : int i, d;
287 : : uint8_t common_depth, ip_xor;
288 : :
289 [ + + + + ]: 2562 : if (unlikely((rib == NULL || ip == NULL || depth > RTE_IPV6_MAX_DEPTH))) {
290 : 2 : rte_errno = EINVAL;
291 : 2 : return NULL;
292 : : }
293 : :
294 : 2560 : tmp = &rib->tree;
295 : :
296 : 2560 : tmp_ip = *ip;
297 [ + + ]: 2560 : rte_ipv6_addr_mask(&tmp_ip, depth);
298 : :
299 : 2560 : new_node = rte_rib6_lookup_exact(rib, &tmp_ip, depth);
300 [ + + ]: 2560 : if (new_node != NULL) {
301 : 1 : rte_errno = EEXIST;
302 : 1 : return NULL;
303 : : }
304 : :
305 : 2559 : new_node = node_alloc(rib);
306 [ - + ]: 2559 : if (new_node == NULL) {
307 : 0 : rte_errno = ENOMEM;
308 : 0 : return NULL;
309 : : }
310 : 2559 : new_node->left = NULL;
311 : 2559 : new_node->right = NULL;
312 : 2559 : new_node->parent = NULL;
313 : 2559 : new_node->ip = tmp_ip;
314 : 2559 : new_node->depth = depth;
315 : 2559 : new_node->flag = RTE_RIB_VALID_NODE;
316 : :
317 : : /* traverse down the tree to find matching node or closest matching */
318 : : while (1) {
319 : : /* insert as the last node in the branch */
320 [ + + ]: 36641 : if (*tmp == NULL) {
321 : 1254 : *tmp = new_node;
322 : 1254 : new_node->parent = prev;
323 : 1254 : ++rib->cur_routes;
324 : 1254 : return *tmp;
325 : : }
326 : : /*
327 : : * Intermediate node found.
328 : : * Previous rte_rib6_lookup_exact() returned NULL
329 : : * but node with proper search criteria is found.
330 : : * Validate intermediate node and return.
331 : : */
332 [ + + - + ]: 35387 : if (rte_ipv6_addr_eq(&tmp_ip, &(*tmp)->ip) && (depth == (*tmp)->depth)) {
333 : 0 : node_free(rib, new_node);
334 : 0 : (*tmp)->flag |= RTE_RIB_VALID_NODE;
335 : 0 : ++rib->cur_routes;
336 : 0 : return *tmp;
337 : : }
338 : :
339 [ + + + + ]: 35387 : if (!rte_ipv6_addr_eq_prefix(&tmp_ip, &(*tmp)->ip, (*tmp)->depth) ||
340 : : ((*tmp)->depth >= depth)) {
341 : : break;
342 : : }
343 : : prev = *tmp;
344 : :
345 [ + + ]: 34082 : tmp = (get_dir(&tmp_ip, (*tmp)->depth)) ? &(*tmp)->right :
346 : : &(*tmp)->left;
347 : : }
348 : :
349 : : /* closest node found, new_node should be inserted in the middle */
350 : 1305 : common_depth = RTE_MIN(depth, (*tmp)->depth);
351 [ + + ]: 14110 : for (i = 0, d = 0; i < RTE_IPV6_ADDR_SIZE; i++) {
352 : 13540 : ip_xor = tmp_ip.a[i] ^ (*tmp)->ip.a[i];
353 [ + + ]: 13540 : if (ip_xor == 0)
354 : 12805 : d += 8;
355 : : else {
356 : 735 : d += rte_clz32((uint32_t)ip_xor << 24);
357 : 735 : break;
358 : : }
359 : : }
360 : :
361 : 1305 : common_depth = RTE_MIN(d, common_depth);
362 : :
363 [ + - ]: 1305 : common_prefix = tmp_ip;
364 : : rte_ipv6_addr_mask(&common_prefix, common_depth);
365 : :
366 [ + + + + ]: 1305 : if (rte_ipv6_addr_eq(&common_prefix, &tmp_ip) &&
367 : : (common_depth == depth)) {
368 : : /* insert as a parent */
369 [ - + ]: 846 : if (get_dir(&(*tmp)->ip, depth))
370 : 0 : new_node->right = *tmp;
371 : : else
372 : 846 : new_node->left = *tmp;
373 : 846 : new_node->parent = (*tmp)->parent;
374 : 846 : (*tmp)->parent = new_node;
375 : 846 : *tmp = new_node;
376 : : } else {
377 : : /* create intermediate node */
378 : 459 : common_node = node_alloc(rib);
379 [ - + ]: 459 : if (common_node == NULL) {
380 : 0 : node_free(rib, new_node);
381 : 0 : rte_errno = ENOMEM;
382 : 0 : return NULL;
383 : : }
384 : 459 : common_node->ip = common_prefix;
385 : 459 : common_node->depth = common_depth;
386 : 459 : common_node->flag = 0;
387 : 459 : common_node->parent = (*tmp)->parent;
388 : 459 : new_node->parent = common_node;
389 : 459 : (*tmp)->parent = common_node;
390 [ + + ]: 459 : if (get_dir(&(*tmp)->ip, common_depth) == 1) {
391 : 283 : common_node->left = new_node;
392 : 283 : common_node->right = *tmp;
393 : : } else {
394 : 176 : common_node->left = *tmp;
395 : 176 : common_node->right = new_node;
396 : : }
397 : 459 : *tmp = common_node;
398 : : }
399 : 1305 : ++rib->cur_routes;
400 : 1305 : return new_node;
401 : : }
402 : :
403 : : RTE_EXPORT_SYMBOL(rte_rib6_get_ip)
404 : : int
405 : 1847 : rte_rib6_get_ip(const struct rte_rib6_node *node,
406 : : struct rte_ipv6_addr *ip)
407 : : {
408 [ + + ]: 1847 : if (unlikely(node == NULL || ip == NULL)) {
409 : 2 : rte_errno = EINVAL;
410 : 2 : return -1;
411 : : }
412 : 1845 : *ip = node->ip;
413 : 1845 : return 0;
414 : : }
415 : :
416 : : RTE_EXPORT_SYMBOL(rte_rib6_get_depth)
417 : : int
418 : 7050 : rte_rib6_get_depth(const struct rte_rib6_node *node, uint8_t *depth)
419 : : {
420 [ + + ]: 7050 : if (unlikely(node == NULL || depth == NULL)) {
421 : 2 : rte_errno = EINVAL;
422 : 2 : return -1;
423 : : }
424 : 7048 : *depth = node->depth;
425 : 7048 : return 0;
426 : : }
427 : :
428 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_rib6_node_has_children)
429 : : bool
430 : 4595 : rte_rib6_node_has_children(const struct rte_rib6_node *node)
431 : : {
432 [ + + + - ]: 4595 : return node->left != NULL || node->right != NULL;
433 : : }
434 : :
435 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_rib6_get_parent)
436 : : struct rte_rib6_node *
437 : 3135 : rte_rib6_get_parent(const struct rte_rib6_node *node)
438 : : {
439 : 3135 : return node->parent;
440 : : }
441 : :
442 : : RTE_EXPORT_SYMBOL(rte_rib6_get_ext)
443 : : void *
444 : 1 : rte_rib6_get_ext(struct rte_rib6_node *node)
445 : : {
446 [ - + ]: 1 : return (node == NULL) ? NULL : &node->ext[0];
447 : : }
448 : :
449 : : RTE_EXPORT_SYMBOL(rte_rib6_get_nh)
450 : : int
451 : 51807 : rte_rib6_get_nh(const struct rte_rib6_node *node, uint64_t *nh)
452 : : {
453 [ + + ]: 51807 : if (unlikely(node == NULL || nh == NULL)) {
454 : 2 : rte_errno = EINVAL;
455 : 2 : return -1;
456 : : }
457 : 51805 : *nh = node->nh;
458 : 51805 : return 0;
459 : : }
460 : :
461 : : RTE_EXPORT_SYMBOL(rte_rib6_set_nh)
462 : : int
463 : 2557 : rte_rib6_set_nh(struct rte_rib6_node *node, uint64_t nh)
464 : : {
465 [ + + ]: 2557 : if (unlikely(node == NULL)) {
466 : 1 : rte_errno = EINVAL;
467 : 1 : return -1;
468 : : }
469 : 2556 : node->nh = nh;
470 : 2556 : return 0;
471 : : }
472 : :
473 : : RTE_EXPORT_SYMBOL(rte_rib6_create)
474 : : struct rte_rib6 *
475 : 27 : rte_rib6_create(const char *name, int socket_id,
476 : : const struct rte_rib6_conf *conf)
477 : : {
478 : : char mem_name[RTE_RIB6_NAMESIZE];
479 : : struct rte_rib6 *rib = NULL;
480 : : struct rte_tailq_entry *te;
481 : : struct rte_rib6_list *rib6_list;
482 : : struct rte_mempool *node_pool;
483 : :
484 : : /* Check user arguments. */
485 [ + + + + ]: 27 : if (unlikely(name == NULL || conf == NULL || conf->max_nodes <= 0)) {
486 : 4 : rte_errno = EINVAL;
487 : 4 : return NULL;
488 : : }
489 : :
490 : : snprintf(mem_name, sizeof(mem_name), "MP_%s", name);
491 : 23 : node_pool = rte_mempool_create(mem_name, conf->max_nodes,
492 : 23 : sizeof(struct rte_rib6_node) + conf->ext_sz, 0, 0,
493 : : NULL, NULL, NULL, NULL, socket_id, 0);
494 : :
495 [ + + ]: 23 : if (node_pool == NULL) {
496 : 2 : RIB_LOG(ERR,
497 : : "Can not allocate mempool for RIB6 %s", name);
498 : 2 : return NULL;
499 : : }
500 : :
501 : : snprintf(mem_name, sizeof(mem_name), "RIB6_%s", name);
502 : 21 : rib6_list = RTE_TAILQ_CAST(rte_rib6_tailq.head, rte_rib6_list);
503 : :
504 : 21 : rte_mcfg_tailq_write_lock();
505 : :
506 : : /* guarantee there's no existing */
507 [ - + ]: 21 : TAILQ_FOREACH(te, rib6_list, next) {
508 : 0 : rib = (struct rte_rib6 *)te->data;
509 [ # # ]: 0 : if (strncmp(name, rib->name, RTE_RIB6_NAMESIZE) == 0)
510 : : break;
511 : : }
512 : : rib = NULL;
513 [ - + ]: 21 : if (te != NULL) {
514 : 0 : rte_errno = EEXIST;
515 : 0 : goto exit;
516 : : }
517 : :
518 : : /* allocate tailq entry */
519 : 21 : te = rte_zmalloc("RIB6_TAILQ_ENTRY", sizeof(*te), 0);
520 [ - + ]: 21 : if (unlikely(te == NULL)) {
521 : 0 : RIB_LOG(ERR,
522 : : "Can not allocate tailq entry for RIB6 %s", name);
523 : 0 : rte_errno = ENOMEM;
524 : 0 : goto exit;
525 : : }
526 : :
527 : : /* Allocate memory to store the RIB6 data structures. */
528 : 21 : rib = rte_zmalloc_socket(mem_name,
529 : : sizeof(struct rte_rib6), RTE_CACHE_LINE_SIZE, socket_id);
530 [ - + ]: 21 : if (unlikely(rib == NULL)) {
531 : 0 : RIB_LOG(ERR, "RIB6 %s memory allocation failed", name);
532 : 0 : rte_errno = ENOMEM;
533 : 0 : goto free_te;
534 : : }
535 : :
536 : 21 : rte_strlcpy(rib->name, name, sizeof(rib->name));
537 : 21 : rib->tree = NULL;
538 : 21 : rib->max_nodes = conf->max_nodes;
539 : 21 : rib->node_pool = node_pool;
540 : :
541 : 21 : te->data = (void *)rib;
542 : 21 : TAILQ_INSERT_TAIL(rib6_list, te, next);
543 : :
544 : 21 : rte_mcfg_tailq_write_unlock();
545 : :
546 : 21 : return rib;
547 : :
548 : : free_te:
549 : 0 : rte_free(te);
550 : 0 : exit:
551 : 0 : rte_mcfg_tailq_write_unlock();
552 : 0 : rte_mempool_free(node_pool);
553 : :
554 : 0 : return NULL;
555 : : }
556 : :
557 : : RTE_EXPORT_SYMBOL(rte_rib6_find_existing)
558 : : struct rte_rib6 *
559 : 0 : rte_rib6_find_existing(const char *name)
560 : : {
561 : : struct rte_rib6 *rib = NULL;
562 : : struct rte_tailq_entry *te;
563 : : struct rte_rib6_list *rib6_list;
564 : :
565 [ # # ]: 0 : if (unlikely(name == NULL)) {
566 : 0 : rte_errno = EINVAL;
567 : 0 : return NULL;
568 : : }
569 : :
570 : 0 : rib6_list = RTE_TAILQ_CAST(rte_rib6_tailq.head, rte_rib6_list);
571 : :
572 : 0 : rte_mcfg_tailq_read_lock();
573 [ # # ]: 0 : TAILQ_FOREACH(te, rib6_list, next) {
574 : 0 : rib = (struct rte_rib6 *) te->data;
575 [ # # ]: 0 : if (strncmp(name, rib->name, RTE_RIB6_NAMESIZE) == 0)
576 : : break;
577 : : }
578 : 0 : rte_mcfg_tailq_read_unlock();
579 : :
580 [ # # ]: 0 : if (te == NULL) {
581 : 0 : rte_errno = ENOENT;
582 : 0 : return NULL;
583 : : }
584 : :
585 : : return rib;
586 : : }
587 : :
588 : : RTE_EXPORT_SYMBOL(rte_rib6_free)
589 : : void
590 : 22 : rte_rib6_free(struct rte_rib6 *rib)
591 : : {
592 : : struct rte_tailq_entry *te;
593 : : struct rte_rib6_list *rib6_list;
594 : : struct rte_rib6_node *tmp = NULL;
595 : :
596 [ + + ]: 22 : if (unlikely(rib == NULL)) {
597 : 1 : rte_errno = EINVAL;
598 : 1 : return;
599 : : }
600 : :
601 : 21 : rib6_list = RTE_TAILQ_CAST(rte_rib6_tailq.head, rte_rib6_list);
602 : :
603 : 21 : rte_mcfg_tailq_write_lock();
604 : :
605 : : /* find our tailq entry */
606 [ + - ]: 21 : TAILQ_FOREACH(te, rib6_list, next) {
607 [ - + ]: 21 : if (te->data == (void *)rib)
608 : : break;
609 : : }
610 [ + - ]: 21 : if (te != NULL)
611 [ - + ]: 21 : TAILQ_REMOVE(rib6_list, te, next);
612 : :
613 : 21 : rte_mcfg_tailq_write_unlock();
614 : :
615 : 21 : while ((tmp = rte_rib6_get_nxt(rib, 0, 0, tmp,
616 [ - + ]: 21 : RTE_RIB6_GET_NXT_ALL)) != NULL)
617 : 0 : rte_rib6_remove(rib, &tmp->ip, tmp->depth);
618 : :
619 : 21 : rte_mempool_free(rib->node_pool);
620 : :
621 : 21 : rte_free(rib);
622 : 21 : rte_free(te);
623 : : }
|