xref: /openbsd/sys/net/art.c (revision 4cfece93)
1 /*	$OpenBSD: art.c,v 1.28 2019/03/31 19:29:27 tb Exp $ */
2 
3 /*
4  * Copyright (c) 2015 Martin Pieuchot
5  * Copyright (c) 2001 Yoichi Hariguchi
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /*
21  * Allotment Routing Table (ART).
22  *
23  * Yoichi Hariguchi paper can be found at:
24  *	http://www.hariguchi.org/art/art.pdf
25  */
26 
27 #ifndef _KERNEL
28 #include "kern_compat.h"
29 #else
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/malloc.h>
33 #include <sys/pool.h>
34 #include <sys/task.h>
35 #include <sys/socket.h>
36 #endif
37 
38 #include <net/art.h>
39 
40 int			 art_bindex(struct art_table *, uint8_t *, int);
41 void			 art_allot(struct art_table *at, int, struct art_node *,
42 			     struct art_node *);
43 struct art_table	*art_table_get(struct art_root *, struct art_table *,
44 			     int);
45 struct art_table	*art_table_put(struct art_root *, struct art_table *);
46 struct art_node		*art_table_insert(struct art_root *, struct art_table *,
47 			     int, struct art_node *);
48 struct art_node		*art_table_delete(struct art_root *, struct art_table *,
49 			     int, struct art_node *);
50 struct art_table	*art_table_ref(struct art_root *, struct art_table *);
51 int			 art_table_free(struct art_root *, struct art_table *);
52 int			 art_table_walk(struct art_root *, struct art_table *,
53 			     int (*f)(struct art_node *, void *), void *);
54 int			 art_walk_apply(struct art_root *,
55 			     struct art_node *, struct art_node *,
56 			     int (*f)(struct art_node *, void *), void *);
57 void			 art_table_gc(void *);
58 void			 art_gc(void *);
59 
60 struct pool		an_pool, at_pool, at_heap_4_pool, at_heap_8_pool;
61 
62 struct art_table	*art_table_gc_list = NULL;
63 struct mutex		 art_table_gc_mtx = MUTEX_INITIALIZER(IPL_SOFTNET);
64 struct task		 art_table_gc_task =
65 			     TASK_INITIALIZER(art_table_gc, NULL);
66 
67 struct art_node		*art_node_gc_list = NULL;
68 struct mutex		 art_node_gc_mtx = MUTEX_INITIALIZER(IPL_SOFTNET);
69 struct task		 art_node_gc_task = TASK_INITIALIZER(art_gc, NULL);
70 
71 void
72 art_init(void)
73 {
74 	pool_init(&an_pool, sizeof(struct art_node), 0, IPL_SOFTNET, 0,
75 	    "art_node", NULL);
76 	pool_init(&at_pool, sizeof(struct art_table), 0, IPL_SOFTNET, 0,
77 	    "art_table", NULL);
78 	pool_init(&at_heap_4_pool, AT_HEAPSIZE(4), 0, IPL_SOFTNET, 0,
79 	    "art_heap4", NULL);
80 	pool_init(&at_heap_8_pool, AT_HEAPSIZE(8), 0, IPL_SOFTNET, 0,
81 	    "art_heap8", &pool_allocator_single);
82 }
83 
84 /*
85  * Per routing table initialization API function.
86  */
87 struct art_root *
88 art_alloc(unsigned int rtableid, unsigned int alen, unsigned int off)
89 {
90 	struct art_root		*ar;
91 	int			 i;
92 
93 	ar = malloc(sizeof(*ar), M_RTABLE, M_NOWAIT|M_ZERO);
94 	if (ar == NULL)
95 		return (NULL);
96 
97 	switch (alen) {
98 	case 32:
99 		ar->ar_alen = 32;
100 		ar->ar_nlvl = 7;
101 		ar->ar_bits[0] = 8;
102 		for (i = 1; i < ar->ar_nlvl; i++)
103 			ar->ar_bits[i] = 4;
104 		break;
105 	case 128:
106 		ar->ar_alen = 128;
107 		ar->ar_nlvl = 32;
108 		for (i = 0; i < ar->ar_nlvl; i++)
109 			ar->ar_bits[i] = 4;
110 		break;
111 	default:
112 		printf("%s: incorrect address length %u\n", __func__, alen);
113 		free(ar, M_RTABLE, sizeof(*ar));
114 		return (NULL);
115 	}
116 
117 	ar->ar_off = off;
118 	ar->ar_rtableid = rtableid;
119 	rw_init(&ar->ar_lock, "art");
120 
121 	return (ar);
122 }
123 
124 /*
125  * Return 1 if ``old'' and ``new`` are identical, 0 otherwise.
126  */
127 static inline int
128 art_check_duplicate(struct art_root *ar, struct art_node *old,
129     struct art_node *new)
130 {
131 	if (old == NULL)
132 		return (0);
133 
134 	if (old->an_plen == new->an_plen)
135 		return (1);
136 
137 	return (0);
138 }
139 
140 /*
141  * Return the base index of the part of ``addr'' and ``plen''
142  * corresponding to the range covered by the table ``at''.
143  *
144  * In other words, this function take the multi-level (complete)
145  * address ``addr'' and prefix length ``plen'' and return the
146  * single level base index for the table ``at''.
147  *
148  * For example with an address size of 32bit divided into four
149  * 8bit-long tables, there's a maximum of 4 base indexes if the
150  * prefix length is > 24.
151  */
152 int
153 art_bindex(struct art_table *at, uint8_t *addr, int plen)
154 {
155 	uint8_t			boff, bend;
156 	uint32_t		k;
157 
158 	if (plen < at->at_offset || plen > (at->at_offset + at->at_bits))
159 		return (-1);
160 
161 	/*
162 	 * We are only interested in the part of the prefix length
163 	 * corresponding to the range of this table.
164 	 */
165 	plen -= at->at_offset;
166 
167 	/*
168 	 * Jump to the first byte of the address containing bits
169 	 * covered by this table.
170 	 */
171 	addr += (at->at_offset / 8);
172 
173 	/* ``at'' covers the bit range between ``boff'' & ``bend''. */
174 	boff = (at->at_offset % 8);
175 	bend = (at->at_bits + boff);
176 
177 	KASSERT(bend <= 32);
178 
179 	if (bend > 24) {
180 		k = (addr[0] & ((1 << (8 - boff)) - 1)) << (bend - 8);
181 		k |= addr[1] << (bend - 16);
182 		k |= addr[2] << (bend - 24);
183 		k |= addr[3] >> (32 - bend);
184 	} else if (bend > 16) {
185 		k = (addr[0] & ((1 << (8 - boff)) - 1)) << (bend - 8);
186 		k |= addr[1] << (bend - 16);
187 		k |= addr[2] >> (24 - bend);
188 	} else if (bend > 8) {
189 		k = (addr[0] & ((1 << (8 - boff)) - 1)) << (bend - 8);
190 		k |= addr[1] >> (16 - bend);
191 	} else {
192 		k = (addr[0] >> (8 - bend)) & ((1 << at->at_bits) - 1);
193 	}
194 
195 	/*
196 	 * Single level base index formula:
197 	 */
198 	return ((k >> (at->at_bits - plen)) + (1 << plen));
199 }
200 
201 /*
202  * Single level lookup function.
203  *
204  * Return the fringe index of the part of ``addr''
205  * corresponding to the range covered by the table ``at''.
206  */
207 static inline int
208 art_findex(struct art_table *at, uint8_t *addr)
209 {
210 	return art_bindex(at, addr, (at->at_offset + at->at_bits));
211 }
212 
213 /*
214  * (Non-perfect) lookup API function.
215  *
216  * Return the best existing match for a destination.
217  */
218 struct art_node *
219 art_match(struct art_root *ar, void *addr, struct srp_ref *nsr)
220 {
221 	struct srp_ref		dsr, ndsr;
222 	void			*entry;
223 	struct art_table	*at;
224 	struct art_node		*dflt, *ndflt;
225 	int			j;
226 
227 	entry = srp_enter(nsr, &ar->ar_root);
228 	at = entry;
229 
230 	if (at == NULL)
231 		goto done;
232 
233 	/*
234 	 * Remember the default route of each table we visit in case
235 	 * we do not find a better matching route.
236 	 */
237 	dflt = srp_enter(&dsr, &at->at_default);
238 
239 	/*
240 	 * Iterate until we find a leaf.
241 	 */
242 	while (1) {
243 		/* Do a single level route lookup. */
244 		j = art_findex(at, addr);
245 		entry = srp_follow(nsr, &at->at_heap[j].node);
246 
247 		/* If this is a leaf (NULL is a leaf) we're done. */
248 		if (ISLEAF(entry))
249 			break;
250 
251 		at = SUBTABLE(entry);
252 
253 		ndflt = srp_enter(&ndsr, &at->at_default);
254 		if (ndflt != NULL) {
255 			srp_leave(&dsr);
256 			dsr = ndsr;
257 			dflt = ndflt;
258 		} else
259 			srp_leave(&ndsr);
260 	}
261 
262 	if (entry == NULL) {
263 		srp_leave(nsr);
264 		*nsr = dsr;
265 		KASSERT(ISLEAF(dflt));
266 		return (dflt);
267 	}
268 
269 	srp_leave(&dsr);
270 done:
271 	KASSERT(ISLEAF(entry));
272 	return (entry);
273 }
274 
275 /*
276  * Perfect lookup API function.
277  *
278  * Return a perfect match for a destination/prefix-length pair or NULL if
279  * it does not exist.
280  */
281 struct art_node *
282 art_lookup(struct art_root *ar, void *addr, int plen, struct srp_ref *nsr)
283 {
284 	void			*entry;
285 	struct art_table	*at;
286 	int			 i, j;
287 
288 	KASSERT(plen >= 0 && plen <= ar->ar_alen);
289 
290 	entry = srp_enter(nsr, &ar->ar_root);
291 	at = entry;
292 
293 	if (at == NULL)
294 		goto done;
295 
296 	/* Default route */
297 	if (plen == 0) {
298 		entry = srp_follow(nsr, &at->at_default);
299 		goto done;
300 	}
301 
302 	/*
303 	 * If the prefix length is smaller than the sum of
304 	 * the stride length at this level the entry must
305 	 * be in the current table.
306 	 */
307 	while (plen > (at->at_offset + at->at_bits)) {
308 		/* Do a single level route lookup. */
309 		j = art_findex(at, addr);
310 		entry = srp_follow(nsr, &at->at_heap[j].node);
311 
312 		/* A leaf is a match, but not a perfect one, or NULL */
313 		if (ISLEAF(entry))
314 			return (NULL);
315 
316 		at = SUBTABLE(entry);
317 	}
318 
319 	i = art_bindex(at, addr, plen);
320 	if (i == -1)
321 		return (NULL);
322 
323 	entry = srp_follow(nsr, &at->at_heap[i].node);
324 	if (!ISLEAF(entry))
325 		entry = srp_follow(nsr, &SUBTABLE(entry)->at_default);
326 
327 done:
328 	KASSERT(ISLEAF(entry));
329 	return (entry);
330 }
331 
332 
333 /*
334  * Insertion API function.
335  *
336  * Insert the given node or return an existing one if a node with the
337  * same destination/mask pair is already present.
338  */
339 struct art_node *
340 art_insert(struct art_root *ar, struct art_node *an, void *addr, int plen)
341 {
342 	struct art_table	*at, *child;
343 	struct art_node		*node;
344 	int			 i, j;
345 
346 	rw_assert_wrlock(&ar->ar_lock);
347 	KASSERT(plen >= 0 && plen <= ar->ar_alen);
348 
349 	at = srp_get_locked(&ar->ar_root);
350 	if (at == NULL) {
351 		at = art_table_get(ar, NULL, -1);
352 		if (at == NULL)
353 			return (NULL);
354 
355 		srp_swap_locked(&ar->ar_root, at);
356 	}
357 
358 	/* Default route */
359 	if (plen == 0) {
360 		node = srp_get_locked(&at->at_default);
361 		if (node != NULL)
362 			return (node);
363 
364 		art_table_ref(ar, at);
365 		srp_swap_locked(&at->at_default, an);
366 		return (an);
367 	}
368 
369 	/*
370 	 * If the prefix length is smaller than the sum of
371 	 * the stride length at this level the entry must
372 	 * be in the current table.
373 	 */
374 	while (plen > (at->at_offset + at->at_bits)) {
375 		/* Do a single level route lookup. */
376 		j = art_findex(at, addr);
377 		node = srp_get_locked(&at->at_heap[j].node);
378 
379 		/*
380 		 * If the node corresponding to the fringe index is
381 		 * a leaf we need to allocate a subtable.  The route
382 		 * entry of this node will then become the default
383 		 * route of the subtable.
384 		 */
385 		if (ISLEAF(node)) {
386 			child = art_table_get(ar, at, j);
387 			if (child == NULL)
388 				return (NULL);
389 
390 			art_table_ref(ar, at);
391 			srp_swap_locked(&at->at_heap[j].node, ASNODE(child));
392 			at = child;
393 		} else
394 			at = SUBTABLE(node);
395 	}
396 
397 	i = art_bindex(at, addr, plen);
398 	if (i == -1)
399 		return (NULL);
400 
401 	return (art_table_insert(ar, at, i, an));
402 }
403 
404 /*
405  * Single level insertion.
406  */
407 struct art_node *
408 art_table_insert(struct art_root *ar, struct art_table *at, int i,
409     struct art_node *an)
410 {
411 	struct art_node	*prev, *node;
412 
413 	node = srp_get_locked(&at->at_heap[i].node);
414 	if (!ISLEAF(node))
415 		prev = srp_get_locked(&SUBTABLE(node)->at_default);
416 	else
417 		prev = node;
418 
419 	if (art_check_duplicate(ar, prev, an))
420 		return (prev);
421 
422 	art_table_ref(ar, at);
423 
424 	/*
425 	 * If the index `i' of the route that we are inserting is not
426 	 * a fringe index, we need to allot this new route pointer to
427 	 * all the corresponding fringe indices.
428 	 */
429 	if (i < at->at_minfringe)
430 		art_allot(at, i, prev, an);
431 	else if (!ISLEAF(node))
432 		srp_swap_locked(&SUBTABLE(node)->at_default, an);
433 	else
434 		srp_swap_locked(&at->at_heap[i].node, an);
435 
436 	return (an);
437 }
438 
439 
440 /*
441  * Deletion API function.
442  */
443 struct art_node *
444 art_delete(struct art_root *ar, struct art_node *an, void *addr, int plen)
445 {
446 	struct art_table	*at;
447 	struct art_node		*node;
448 	int			 i, j;
449 
450 	rw_assert_wrlock(&ar->ar_lock);
451 	KASSERT(plen >= 0 && plen <= ar->ar_alen);
452 
453 	at = srp_get_locked(&ar->ar_root);
454 	if (at == NULL)
455 		return (NULL);
456 
457 	/* Default route */
458 	if (plen == 0) {
459 		node = srp_get_locked(&at->at_default);
460 		srp_swap_locked(&at->at_default, NULL);
461 		art_table_free(ar, at);
462 		return (node);
463 	}
464 
465 	/*
466 	 * If the prefix length is smaller than the sum of
467 	 * the stride length at this level the entry must
468 	 * be in the current table.
469 	 */
470 	while (plen > (at->at_offset + at->at_bits)) {
471 		/* Do a single level route lookup. */
472 		j = art_findex(at, addr);
473 		node = srp_get_locked(&at->at_heap[j].node);
474 
475 		/* If this is a leaf, there is no route to delete. */
476 		if (ISLEAF(node))
477 			return (NULL);
478 
479 		at = SUBTABLE(node);
480 	}
481 
482 	i = art_bindex(at, addr, plen);
483 	if (i == -1)
484 		return (NULL);
485 
486 	return (art_table_delete(ar, at, i, an));
487 }
488 
489 /*
490  * Single level deletion.
491  */
492 struct art_node *
493 art_table_delete(struct art_root *ar, struct art_table *at, int i,
494     struct art_node *an)
495 {
496 	struct art_node		*next, *node;
497 
498 #ifdef DIAGNOSTIC
499 	struct art_node		*prev;
500 #endif
501 
502 	node = srp_get_locked(&at->at_heap[i].node);
503 #ifdef DIAGNOSTIC
504 	if (!ISLEAF(node))
505 		prev = srp_get_locked(&SUBTABLE(node)->at_default);
506 	else
507 		prev = node;
508 
509 	KASSERT(prev == an);
510 #endif
511 
512 	/* Get the next most specific route for the index `i'. */
513 	if ((i >> 1) > 1)
514 		next = srp_get_locked(&at->at_heap[i >> 1].node);
515 	else
516 		next = NULL;
517 
518 	/*
519 	 * If the index `i' of the route that we are removing is not
520 	 * a fringe index, we need to allot the next most specific
521 	 * route pointer to all the corresponding fringe indices.
522 	 */
523 	if (i < at->at_minfringe)
524 		art_allot(at, i, an, next);
525 	else if (!ISLEAF(node))
526 		srp_swap_locked(&SUBTABLE(node)->at_default, next);
527 	else
528 		srp_swap_locked(&at->at_heap[i].node, next);
529 
530 	/* We have removed an entry from this table. */
531 	art_table_free(ar, at);
532 
533 	return (an);
534 }
535 
536 struct art_table *
537 art_table_ref(struct art_root *ar, struct art_table *at)
538 {
539 	at->at_refcnt++;
540 	return (at);
541 }
542 
543 static inline int
544 art_table_rele(struct art_table *at)
545 {
546 	if (at == NULL)
547 		return (0);
548 
549 	return (--at->at_refcnt == 0);
550 }
551 
552 int
553 art_table_free(struct art_root *ar, struct art_table *at)
554 {
555 	if (art_table_rele(at)) {
556 		/*
557 		 * Garbage collect this table and all its parents
558 		 * that are empty.
559 		 */
560 		do {
561 			at = art_table_put(ar, at);
562 		} while (art_table_rele(at));
563 
564 		return (1);
565 	}
566 
567 	return (0);
568 }
569 
570 /*
571  * Iteration API function.
572  */
573 int
574 art_walk(struct art_root *ar, int (*f)(struct art_node *, void *), void *arg)
575 {
576 	struct srp_ref		 sr;
577 	struct art_table	*at;
578 	struct art_node		*node;
579 	int			 error = 0;
580 
581 	rw_enter_write(&ar->ar_lock);
582 	at = srp_get_locked(&ar->ar_root);
583 	if (at != NULL) {
584 		art_table_ref(ar, at);
585 
586 		/*
587 		 * The default route should be processed here because the root
588 		 * table does not have a parent.
589 		 */
590 		node = srp_enter(&sr, &at->at_default);
591 		error = art_walk_apply(ar, node, NULL, f, arg);
592 		srp_leave(&sr);
593 
594 		if (error == 0)
595 			error = art_table_walk(ar, at, f, arg);
596 
597 		art_table_free(ar, at);
598 	}
599 	rw_exit_write(&ar->ar_lock);
600 
601 	return (error);
602 }
603 
604 int
605 art_table_walk(struct art_root *ar, struct art_table *at,
606     int (*f)(struct art_node *, void *), void *arg)
607 {
608 	struct srp_ref		 sr;
609 	struct art_node		*node, *next;
610 	struct art_table	*nat;
611 	int			 i, j, error = 0;
612 	uint32_t		 maxfringe = (at->at_minfringe << 1);
613 
614 	/*
615 	 * Iterate non-fringe nodes in ``natural'' order.
616 	 */
617 	for (j = 1; j < at->at_minfringe; j += 2) {
618 		/*
619 		 * The default route (index 1) is processed by the
620 		 * parent table (where it belongs) otherwise it could
621 		 * be processed more than once.
622 		 */
623 		for (i = max(j, 2); i < at->at_minfringe; i <<= 1) {
624 			next = srp_get_locked(&at->at_heap[i >> 1].node);
625 
626 			node = srp_enter(&sr, &at->at_heap[i].node);
627 			error = art_walk_apply(ar, node, next, f, arg);
628 			srp_leave(&sr);
629 
630 			if (error != 0)
631 				return (error);
632 		}
633 	}
634 
635 	/*
636 	 * Iterate fringe nodes.
637 	 */
638 	for (i = at->at_minfringe; i < maxfringe; i++) {
639 		next = srp_get_locked(&at->at_heap[i >> 1].node);
640 
641 		node = srp_enter(&sr, &at->at_heap[i].node);
642 		if (!ISLEAF(node)) {
643 			nat = art_table_ref(ar, SUBTABLE(node));
644 			node = srp_follow(&sr, &nat->at_default);
645 		} else
646 			nat = NULL;
647 
648 		error = art_walk_apply(ar, node, next, f, arg);
649 		srp_leave(&sr);
650 
651 		if (error != 0) {
652 			art_table_free(ar, nat);
653 			return (error);
654 		}
655 
656 		if (nat != NULL) {
657 			error = art_table_walk(ar, nat, f, arg);
658 			art_table_free(ar, nat);
659 			if (error != 0)
660 				return (error);
661 		}
662 	}
663 
664 	return (0);
665 }
666 
667 int
668 art_walk_apply(struct art_root *ar,
669     struct art_node *an, struct art_node *next,
670     int (*f)(struct art_node *, void *), void *arg)
671 {
672 	int error = 0;
673 
674 	if ((an != NULL) && (an != next)) {
675 		rw_exit_write(&ar->ar_lock);
676 		error = (*f)(an, arg);
677 		rw_enter_write(&ar->ar_lock);
678 	}
679 
680 	return (error);
681 }
682 
683 
684 /*
685  * Create a table and use the given index to set its default route.
686  *
687  * Note:  This function does not modify the root or the parent.
688  */
689 struct art_table *
690 art_table_get(struct art_root *ar, struct art_table *parent, int j)
691 {
692 	struct art_table	*at;
693 	struct art_node		*node;
694 	void			*at_heap;
695 	uint32_t		 lvl;
696 
697 	KASSERT(j != 0 && j != 1);
698 	KASSERT(parent != NULL || j == -1);
699 
700 	if (parent != NULL)
701 		lvl = parent->at_level + 1;
702 	else
703 		lvl = 0;
704 
705 	KASSERT(lvl < ar->ar_nlvl);
706 
707 	at = pool_get(&at_pool, PR_NOWAIT|PR_ZERO);
708 	if (at == NULL)
709 		return (NULL);
710 
711 	switch (AT_HEAPSIZE(ar->ar_bits[lvl])) {
712 	case AT_HEAPSIZE(4):
713 		at_heap = pool_get(&at_heap_4_pool, PR_NOWAIT|PR_ZERO);
714 		break;
715 	case AT_HEAPSIZE(8):
716 		at_heap = pool_get(&at_heap_8_pool, PR_NOWAIT|PR_ZERO);
717 		break;
718 	default:
719 		panic("incorrect stride length %u", ar->ar_bits[lvl]);
720 	}
721 
722 	if (at_heap == NULL) {
723 		pool_put(&at_pool, at);
724 		return (NULL);
725 	}
726 
727 	at->at_parent = parent;
728 	at->at_index = j;
729 	at->at_minfringe = (1 << ar->ar_bits[lvl]);
730 	at->at_level = lvl;
731 	at->at_bits = ar->ar_bits[lvl];
732 	at->at_heap = at_heap;
733 	at->at_refcnt = 0;
734 
735 	if (parent != NULL) {
736 		node = srp_get_locked(&parent->at_heap[j].node);
737 		/* node isn't being deleted, no srp_finalize needed */
738 		srp_swap_locked(&at->at_default, node);
739 		at->at_offset = (parent->at_offset + parent->at_bits);
740 	}
741 
742 	return (at);
743 }
744 
745 
746 /*
747  * Delete a table and use its index to restore its parent's default route.
748  *
749  * Note:  Modify its parent to unlink the table from it.
750  */
751 struct art_table *
752 art_table_put(struct art_root *ar, struct art_table *at)
753 {
754 	struct art_table	*parent = at->at_parent;
755 	struct art_node		*node;
756 	uint32_t		 j = at->at_index;
757 
758 	KASSERT(at->at_refcnt == 0);
759 	KASSERT(j != 0 && j != 1);
760 
761 	if (parent != NULL) {
762 		KASSERT(j != -1);
763 		KASSERT(at->at_level == parent->at_level + 1);
764 		KASSERT(parent->at_refcnt >= 1);
765 
766 		/* Give the route back to its parent. */
767 		node = srp_get_locked(&at->at_default);
768 		srp_swap_locked(&parent->at_heap[j].node, node);
769 	} else {
770 		KASSERT(j == -1);
771 		KASSERT(at->at_level == 0);
772 		srp_swap_locked(&ar->ar_root, NULL);
773 	}
774 
775 	mtx_enter(&art_table_gc_mtx);
776 	at->at_parent = art_table_gc_list;
777 	art_table_gc_list = at;
778 	mtx_leave(&art_table_gc_mtx);
779 
780 	task_add(systqmp, &art_table_gc_task);
781 
782 	return (parent);
783 }
784 
785 void
786 art_table_gc(void *null)
787 {
788 	struct art_table *at, *next;
789 
790 	mtx_enter(&art_table_gc_mtx);
791 	at = art_table_gc_list;
792 	art_table_gc_list = NULL;
793 	mtx_leave(&art_table_gc_mtx);
794 
795 	while (at != NULL) {
796 		next = at->at_parent;
797 
798 		if (at->at_level == 0)
799 			srp_finalize(at, "arttfini");
800 		else
801 			srp_finalize(ASNODE(at), "arttfini");
802 
803 		switch (AT_HEAPSIZE(at->at_bits)) {
804 		case AT_HEAPSIZE(4):
805 			pool_put(&at_heap_4_pool, at->at_heap);
806 			break;
807 		case AT_HEAPSIZE(8):
808 			pool_put(&at_heap_8_pool, at->at_heap);
809 			break;
810 		default:
811 			panic("incorrect stride length %u", at->at_bits);
812 		}
813 
814 		pool_put(&at_pool, at);
815 
816 		at = next;
817 	}
818 }
819 
820 /*
821  * Substitute a node by another in the subtree whose root index is given.
822  *
823  * This function iterates on the table ``at'' at index ``i'' until no
824  * more ``old'' node can be replaced by ``new''.
825  *
826  * This function was originally written by Don Knuth in CWEB. The
827  * complicated ``goto''s are the result of expansion of the two
828  * following recursions:
829  *
830  *	art_allot(at, i, old, new)
831  *	{
832  *		int k = i;
833  *		if (at->at_heap[k] == old)
834  *			at->at_heap[k] = new;
835  *		if (k >= at->at_minfringe)
836  *			 return;
837  *		k <<= 1;
838  *		art_allot(at, k, old, new);
839  *		k++;
840  *		art_allot(at, k, old, new);
841  *	}
842  */
843 void
844 art_allot(struct art_table *at, int i, struct art_node *old,
845     struct art_node *new)
846 {
847 	struct art_node		*node, *dflt;
848 	int			 k = i;
849 
850 	KASSERT(i < at->at_minfringe);
851 
852 again:
853 	k <<= 1;
854 	if (k < at->at_minfringe)
855 		goto nonfringe;
856 
857 	/* Change fringe nodes. */
858 	while (1) {
859 		node = srp_get_locked(&at->at_heap[k].node);
860 		if (!ISLEAF(node)) {
861 			dflt = srp_get_locked(&SUBTABLE(node)->at_default);
862 			if (dflt == old) {
863 				srp_swap_locked(&SUBTABLE(node)->at_default,
864 				    new);
865 			}
866 		} else if (node == old) {
867 			srp_swap_locked(&at->at_heap[k].node, new);
868 		}
869 		if (k % 2)
870 			goto moveup;
871 		k++;
872 	}
873 
874 nonfringe:
875 	node = srp_get_locked(&at->at_heap[k].node);
876 	if (node == old)
877 		goto again;
878 moveon:
879 	if (k % 2)
880 		goto moveup;
881 	k++;
882 	goto nonfringe;
883 moveup:
884 	k >>= 1;
885 	srp_swap_locked(&at->at_heap[k].node, new);
886 
887 	/* Change non-fringe node. */
888 	if (k != i)
889 		goto moveon;
890 }
891 
892 struct art_node *
893 art_get(void *dst, uint8_t plen)
894 {
895 	struct art_node		*an;
896 
897 	an = pool_get(&an_pool, PR_NOWAIT | PR_ZERO);
898 	if (an == NULL)
899 		return (NULL);
900 
901 	an->an_plen = plen;
902 	SRPL_INIT(&an->an_rtlist);
903 
904 	return (an);
905 }
906 
907 void
908 art_put(struct art_node *an)
909 {
910 	KASSERT(SRPL_EMPTY_LOCKED(&an->an_rtlist));
911 
912 	mtx_enter(&art_node_gc_mtx);
913 	an->an_gc = art_node_gc_list;
914 	art_node_gc_list = an;
915 	mtx_leave(&art_node_gc_mtx);
916 
917 	task_add(systqmp, &art_node_gc_task);
918 }
919 
920 void
921 art_gc(void *null)
922 {
923 	struct art_node		*an, *next;
924 
925 	mtx_enter(&art_node_gc_mtx);
926 	an = art_node_gc_list;
927 	art_node_gc_list = NULL;
928 	mtx_leave(&art_node_gc_mtx);
929 
930 	while (an != NULL) {
931 		next = an->an_gc;
932 
933 		srp_finalize(an, "artnfini");
934 
935 		pool_put(&an_pool, an);
936 
937 		an = next;
938 	}
939 }
940