1df6ad731Slogwang /*- 2*d4a07e70Sfengbojiang * SPDX-License-Identifier: BSD-3-Clause 3*d4a07e70Sfengbojiang * 4df6ad731Slogwang * Copyright (c) 1988, 1989, 1993 5df6ad731Slogwang * The Regents of the University of California. All rights reserved. 6df6ad731Slogwang * 7df6ad731Slogwang * Redistribution and use in source and binary forms, with or without 8df6ad731Slogwang * modification, are permitted provided that the following conditions 9df6ad731Slogwang * are met: 10df6ad731Slogwang * 1. Redistributions of source code must retain the above copyright 11df6ad731Slogwang * notice, this list of conditions and the following disclaimer. 12df6ad731Slogwang * 2. Redistributions in binary form must reproduce the above copyright 13df6ad731Slogwang * notice, this list of conditions and the following disclaimer in the 14df6ad731Slogwang * documentation and/or other materials provided with the distribution. 15*d4a07e70Sfengbojiang * 3. Neither the name of the University nor the names of its contributors 16df6ad731Slogwang * may be used to endorse or promote products derived from this software 17df6ad731Slogwang * without specific prior written permission. 18df6ad731Slogwang * 19df6ad731Slogwang * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20df6ad731Slogwang * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21df6ad731Slogwang * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22df6ad731Slogwang * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23df6ad731Slogwang * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24df6ad731Slogwang * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25df6ad731Slogwang * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26df6ad731Slogwang * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27df6ad731Slogwang * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28df6ad731Slogwang * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29df6ad731Slogwang * SUCH DAMAGE. 30df6ad731Slogwang * 31df6ad731Slogwang * @(#)radix.h 8.2 (Berkeley) 10/31/94 32df6ad731Slogwang * $FreeBSD$ 33df6ad731Slogwang */ 34df6ad731Slogwang 35df6ad731Slogwang #ifndef _RADIX_H_ 36df6ad731Slogwang #define _RADIX_H_ 37df6ad731Slogwang 38*d4a07e70Sfengbojiang #ifdef _KERNEL 39*d4a07e70Sfengbojiang #include <sys/_lock.h> 40*d4a07e70Sfengbojiang #include <sys/_mutex.h> 41*d4a07e70Sfengbojiang #include <sys/_rmlock.h> 42*d4a07e70Sfengbojiang #endif 43*d4a07e70Sfengbojiang 44*d4a07e70Sfengbojiang #ifdef MALLOC_DECLARE 45*d4a07e70Sfengbojiang MALLOC_DECLARE(M_RTABLE); 46*d4a07e70Sfengbojiang #endif 47*d4a07e70Sfengbojiang 48df6ad731Slogwang /* 49df6ad731Slogwang * Radix search tree node layout. 50df6ad731Slogwang */ 51df6ad731Slogwang 52df6ad731Slogwang struct radix_node { 53df6ad731Slogwang struct radix_mask *rn_mklist; /* list of masks contained in subtree */ 54df6ad731Slogwang struct radix_node *rn_parent; /* parent */ 55df6ad731Slogwang short rn_bit; /* bit offset; -1-index(netmask) */ 56df6ad731Slogwang char rn_bmask; /* node: mask for bit test*/ 57df6ad731Slogwang u_char rn_flags; /* enumerated next */ 58df6ad731Slogwang #define RNF_NORMAL 1 /* leaf contains normal route */ 59df6ad731Slogwang #define RNF_ROOT 2 /* leaf is root leaf for tree */ 60df6ad731Slogwang #define RNF_ACTIVE 4 /* This node is alive (for rtfree) */ 61df6ad731Slogwang union { 62df6ad731Slogwang struct { /* leaf only data: */ 63df6ad731Slogwang caddr_t rn_Key; /* object of search */ 64df6ad731Slogwang caddr_t rn_Mask; /* netmask, if present */ 65df6ad731Slogwang struct radix_node *rn_Dupedkey; 66df6ad731Slogwang } rn_leaf; 67df6ad731Slogwang struct { /* node only data: */ 68df6ad731Slogwang int rn_Off; /* where to start compare */ 69df6ad731Slogwang struct radix_node *rn_L;/* progeny */ 70df6ad731Slogwang struct radix_node *rn_R;/* progeny */ 71df6ad731Slogwang } rn_node; 72df6ad731Slogwang } rn_u; 73df6ad731Slogwang #ifdef RN_DEBUG 74df6ad731Slogwang int rn_info; 75df6ad731Slogwang struct radix_node *rn_twin; 76df6ad731Slogwang struct radix_node *rn_ybro; 77df6ad731Slogwang #endif 78df6ad731Slogwang }; 79df6ad731Slogwang 80df6ad731Slogwang #define rn_dupedkey rn_u.rn_leaf.rn_Dupedkey 81df6ad731Slogwang #define rn_key rn_u.rn_leaf.rn_Key 82df6ad731Slogwang #define rn_mask rn_u.rn_leaf.rn_Mask 83df6ad731Slogwang #define rn_offset rn_u.rn_node.rn_Off 84df6ad731Slogwang #define rn_left rn_u.rn_node.rn_L 85df6ad731Slogwang #define rn_right rn_u.rn_node.rn_R 86df6ad731Slogwang 87df6ad731Slogwang /* 88df6ad731Slogwang * Annotations to tree concerning potential routes applying to subtrees. 89df6ad731Slogwang */ 90df6ad731Slogwang 91df6ad731Slogwang struct radix_mask { 92df6ad731Slogwang short rm_bit; /* bit offset; -1-index(netmask) */ 93df6ad731Slogwang char rm_unused; /* cf. rn_bmask */ 94df6ad731Slogwang u_char rm_flags; /* cf. rn_flags */ 95df6ad731Slogwang struct radix_mask *rm_mklist; /* more masks to try */ 96df6ad731Slogwang union { 97df6ad731Slogwang caddr_t rmu_mask; /* the mask */ 98df6ad731Slogwang struct radix_node *rmu_leaf; /* for normal routes */ 99df6ad731Slogwang } rm_rmu; 100df6ad731Slogwang int rm_refs; /* # of references to this struct */ 101df6ad731Slogwang }; 102df6ad731Slogwang 103df6ad731Slogwang #define rm_mask rm_rmu.rmu_mask 104df6ad731Slogwang #define rm_leaf rm_rmu.rmu_leaf /* extra field would make 32 bytes */ 105df6ad731Slogwang 106df6ad731Slogwang struct radix_head; 107df6ad731Slogwang 108df6ad731Slogwang typedef int walktree_f_t(struct radix_node *, void *); 109df6ad731Slogwang typedef struct radix_node *rn_matchaddr_f_t(void *v, 110df6ad731Slogwang struct radix_head *head); 111df6ad731Slogwang typedef struct radix_node *rn_addaddr_f_t(void *v, void *mask, 112df6ad731Slogwang struct radix_head *head, struct radix_node nodes[]); 113df6ad731Slogwang typedef struct radix_node *rn_deladdr_f_t(void *v, void *mask, 114df6ad731Slogwang struct radix_head *head); 115df6ad731Slogwang typedef struct radix_node *rn_lookup_f_t(void *v, void *mask, 116df6ad731Slogwang struct radix_head *head); 117df6ad731Slogwang typedef int rn_walktree_t(struct radix_head *head, walktree_f_t *f, 118df6ad731Slogwang void *w); 119df6ad731Slogwang typedef int rn_walktree_from_t(struct radix_head *head, 120df6ad731Slogwang void *a, void *m, walktree_f_t *f, void *w); 121df6ad731Slogwang typedef void rn_close_t(struct radix_node *rn, struct radix_head *head); 122df6ad731Slogwang 123df6ad731Slogwang struct radix_mask_head; 124df6ad731Slogwang 125df6ad731Slogwang struct radix_head { 126df6ad731Slogwang struct radix_node *rnh_treetop; 127df6ad731Slogwang struct radix_mask_head *rnh_masks; /* Storage for our masks */ 128df6ad731Slogwang }; 129df6ad731Slogwang 130df6ad731Slogwang struct radix_node_head { 131df6ad731Slogwang struct radix_head rh; 132df6ad731Slogwang rn_matchaddr_f_t *rnh_matchaddr; /* longest match for sockaddr */ 133df6ad731Slogwang rn_addaddr_f_t *rnh_addaddr; /* add based on sockaddr*/ 134df6ad731Slogwang rn_deladdr_f_t *rnh_deladdr; /* remove based on sockaddr */ 135df6ad731Slogwang rn_lookup_f_t *rnh_lookup; /* exact match for sockaddr */ 136df6ad731Slogwang rn_walktree_t *rnh_walktree; /* traverse tree */ 137df6ad731Slogwang rn_walktree_from_t *rnh_walktree_from; /* traverse tree below a */ 138df6ad731Slogwang rn_close_t *rnh_close; /*do something when the last ref drops*/ 139df6ad731Slogwang struct radix_node rnh_nodes[3]; /* empty tree for common case */ 140df6ad731Slogwang #ifdef _KERNEL 141*d4a07e70Sfengbojiang struct rmlock rnh_lock; /* locks entire radix tree */ 142df6ad731Slogwang #endif 143df6ad731Slogwang }; 144df6ad731Slogwang 145df6ad731Slogwang struct radix_mask_head { 146df6ad731Slogwang struct radix_head head; 147df6ad731Slogwang struct radix_node mask_nodes[3]; 148df6ad731Slogwang }; 149df6ad731Slogwang 150df6ad731Slogwang void rn_inithead_internal(struct radix_head *rh, struct radix_node *base_nodes, 151df6ad731Slogwang int off); 152df6ad731Slogwang 153df6ad731Slogwang #ifndef _KERNEL 154df6ad731Slogwang #define R_Malloc(p, t, n) (p = (t) malloc((unsigned int)(n))) 155df6ad731Slogwang #define R_Zalloc(p, t, n) (p = (t) calloc(1,(unsigned int)(n))) 156df6ad731Slogwang #define R_Free(p) free((char *)p); 157df6ad731Slogwang #else 158df6ad731Slogwang #define R_Malloc(p, t, n) (p = (t) malloc((unsigned long)(n), M_RTABLE, M_NOWAIT)) 159df6ad731Slogwang #define R_Zalloc(p, t, n) (p = (t) malloc((unsigned long)(n), M_RTABLE, M_NOWAIT | M_ZERO)) 160df6ad731Slogwang #define R_Free(p) free((caddr_t)p, M_RTABLE); 161df6ad731Slogwang 162*d4a07e70Sfengbojiang #define RADIX_NODE_HEAD_RLOCK_TRACKER struct rm_priotracker _rnh_tracker 163df6ad731Slogwang #define RADIX_NODE_HEAD_LOCK_INIT(rnh) \ 164*d4a07e70Sfengbojiang rm_init(&(rnh)->rnh_lock, "radix node head") 165*d4a07e70Sfengbojiang #define RADIX_NODE_HEAD_LOCK(rnh) rm_wlock(&(rnh)->rnh_lock) 166*d4a07e70Sfengbojiang #define RADIX_NODE_HEAD_UNLOCK(rnh) rm_wunlock(&(rnh)->rnh_lock) 167*d4a07e70Sfengbojiang #define RADIX_NODE_HEAD_RLOCK(rnh) rm_rlock(&(rnh)->rnh_lock,\ 168*d4a07e70Sfengbojiang &_rnh_tracker) 169*d4a07e70Sfengbojiang #define RADIX_NODE_HEAD_RUNLOCK(rnh) rm_runlock(&(rnh)->rnh_lock,\ 170*d4a07e70Sfengbojiang &_rnh_tracker) 171*d4a07e70Sfengbojiang #define RADIX_NODE_HEAD_DESTROY(rnh) rm_destroy(&(rnh)->rnh_lock) 172*d4a07e70Sfengbojiang #define RADIX_NODE_HEAD_LOCK_ASSERT(rnh) rm_assert(&(rnh)->rnh_lock, RA_LOCKED) 173*d4a07e70Sfengbojiang #define RADIX_NODE_HEAD_WLOCK_ASSERT(rnh) rm_assert(&(rnh)->rnh_lock, RA_WLOCKED) 174df6ad731Slogwang #endif /* _KERNEL */ 175df6ad731Slogwang 176*d4a07e70Sfengbojiang int rn_inithead(void **, int); 177*d4a07e70Sfengbojiang int rn_detachhead(void **); 178*d4a07e70Sfengbojiang int rn_refines(void *, void *); 179*d4a07e70Sfengbojiang struct radix_node *rn_addroute(void *, void *, struct radix_head *, 180*d4a07e70Sfengbojiang struct radix_node[2]); 181*d4a07e70Sfengbojiang struct radix_node *rn_delete(void *, void *, struct radix_head *); 182*d4a07e70Sfengbojiang struct radix_node *rn_lookup (void *v_arg, void *m_arg, 183*d4a07e70Sfengbojiang struct radix_head *head); 184*d4a07e70Sfengbojiang struct radix_node *rn_match(void *, struct radix_head *); 185*d4a07e70Sfengbojiang int rn_walktree_from(struct radix_head *h, void *a, void *m, 186*d4a07e70Sfengbojiang walktree_f_t *f, void *w); 187*d4a07e70Sfengbojiang int rn_walktree(struct radix_head *, walktree_f_t *, void *); 188*d4a07e70Sfengbojiang 189df6ad731Slogwang #endif /* _RADIX_H_ */ 190