11558Srgrimes/*-
21558Srgrimes * Copyright (c) 1988, 1989, 1993
31558Srgrimes *	The Regents of the University of California.  All rights reserved.
41558Srgrimes *
51558Srgrimes * Redistribution and use in source and binary forms, with or without
61558Srgrimes * modification, are permitted provided that the following conditions
71558Srgrimes * are met:
81558Srgrimes * 1. Redistributions of source code must retain the above copyright
91558Srgrimes *    notice, this list of conditions and the following disclaimer.
101558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111558Srgrimes *    notice, this list of conditions and the following disclaimer in the
121558Srgrimes *    documentation and/or other materials provided with the distribution.
131558Srgrimes * 4. Neither the name of the University nor the names of its contributors
141558Srgrimes *    may be used to endorse or promote products derived from this software
151558Srgrimes *    without specific prior written permission.
161558Srgrimes *
171558Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
181558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
191558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
201558Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
211558Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
221558Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
231558Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
241558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
251558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
261558Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
271558Srgrimes * SUCH DAMAGE.
281558Srgrimes *
291558Srgrimes *	@(#)radix.h	8.2 (Berkeley) 10/31/94
301558Srgrimes * $FreeBSD$
3136997Scharnier */
3223672Speter
3336997Scharnier#ifndef _RADIX_H_
3436997Scharnier#define	_RADIX_H_
3550476Speter
361558Srgrimes#ifdef _KERNEL
371558Srgrimes#include <sys/_lock.h>
381558Srgrimes#include <sys/_mutex.h>
391558Srgrimes#include <sys/_rwlock.h>
401558Srgrimes#endif
411558Srgrimes
421558Srgrimes#ifdef MALLOC_DECLARE
4323672SpeterMALLOC_DECLARE(M_RTABLE);
441558Srgrimes#endif
451558Srgrimes
461558Srgrimes/*
471558Srgrimes * Radix search tree node layout.
4899562Siedowse */
4999562Siedowse
50103949Smikestruct radix_node {
511558Srgrimes	struct	radix_mask *rn_mklist;	/* list of masks contained in subtree */
5299562Siedowse	struct	radix_node *rn_parent;	/* parent */
531558Srgrimes	short	rn_bit;			/* bit offset; -1-index(netmask) */
5499562Siedowse	char	rn_bmask;		/* node: mask for bit test*/
551558Srgrimes	u_char	rn_flags;		/* enumerated next */
561558Srgrimes#define RNF_NORMAL	1		/* leaf contains normal route */
571558Srgrimes#define RNF_ROOT	2		/* leaf is root leaf for tree */
581558Srgrimes#define RNF_ACTIVE	4		/* This node is alive (for rtfree) */
5998542Smckusick	union {
6098542Smckusick		struct {			/* leaf only data: */
6198542Smckusick			caddr_t	rn_Key;		/* object of search */
6298542Smckusick			caddr_t	rn_Mask;	/* netmask, if present */
6398542Smckusick			struct	radix_node *rn_Dupedkey;
6498542Smckusick		} rn_leaf;
6598542Smckusick		struct {			/* node only data: */
66132762Skan			int	rn_Off;		/* where to start compare */
67132762Skan			struct	radix_node *rn_L;/* progeny */
68132762Skan			struct	radix_node *rn_R;/* progeny */
69132762Skan		} rn_node;
70132762Skan	}		rn_u;
71132762Skan#ifdef RN_DEBUG
7298542Smckusick	int rn_info;
731558Srgrimes	struct radix_node *rn_twin;
741558Srgrimes	struct radix_node *rn_ybro;
751558Srgrimes#endif
7698542Smckusick};
77157660Sdwmalone
78167011Smckusick#define	rn_dupedkey	rn_u.rn_leaf.rn_Dupedkey
79167011Smckusick#define	rn_key		rn_u.rn_leaf.rn_Key
80167011Smckusick#define	rn_mask		rn_u.rn_leaf.rn_Mask
81167011Smckusick#define	rn_offset	rn_u.rn_node.rn_Off
82167011Smckusick#define	rn_left		rn_u.rn_node.rn_L
83167011Smckusick#define	rn_right	rn_u.rn_node.rn_R
84167011Smckusick
8598542Smckusick/*
86157660Sdwmalone * Annotations to tree concerning potential routes applying to subtrees.
87107542Smckusick */
881558Srgrimes
891558Srgrimesstruct radix_mask {
901558Srgrimes	short	rm_bit;			/* bit offset; -1-index(netmask) */
911558Srgrimes	char	rm_unused;		/* cf. rn_bmask */
921558Srgrimes	u_char	rm_flags;		/* cf. rn_flags */
931558Srgrimes	struct	radix_mask *rm_mklist;	/* more masks to try */
941558Srgrimes	union	{
951558Srgrimes		caddr_t	rmu_mask;		/* the mask */
96107542Smckusick		struct	radix_node *rmu_leaf;	/* for normal routes */
9798542Smckusick	}	rm_rmu;
981558Srgrimes	int	rm_refs;		/* # of references to this struct */
991558Srgrimes};
1001558Srgrimes
1011558Srgrimes#define	rm_mask rm_rmu.rmu_mask
1021558Srgrimes#define	rm_leaf rm_rmu.rmu_leaf		/* extra field would make 32 bytes */
1031558Srgrimes
1041558Srgrimestypedef int walktree_f_t(struct radix_node *, void *);
1051558Srgrimes
1061558Srgrimesstruct radix_node_head {
1071558Srgrimes	struct	radix_node *rnh_treetop;
1081558Srgrimes	u_int	rnh_gen;		/* generation counter */
1091558Srgrimes	int	rnh_multipath;		/* multipath capable ? */
1101558Srgrimes	int	rnh_addrsize;		/* permit, but not require fixed keys */
1111558Srgrimes	int	rnh_pktsize;		/* permit, but not require fixed keys */
1121558Srgrimes	struct	radix_node *(*rnh_addaddr)	/* add based on sockaddr */
1131558Srgrimes		(void *v, void *mask,
1141558Srgrimes		     struct radix_node_head *head, struct radix_node nodes[]);
115107542Smckusick	struct	radix_node *(*rnh_addpkt)	/* add based on packet hdr */
116107542Smckusick		(void *v, void *mask,
11798542Smckusick		     struct radix_node_head *head, struct radix_node nodes[]);
11898542Smckusick	struct	radix_node *(*rnh_deladdr)	/* remove based on sockaddr */
1191558Srgrimes		(void *v, void *mask, struct radix_node_head *head);
1201558Srgrimes	struct	radix_node *(*rnh_delpkt)	/* remove based on packet hdr */
12198542Smckusick		(void *v, void *mask, struct radix_node_head *head);
1221558Srgrimes	struct	radix_node *(*rnh_matchaddr)	/* longest match for sockaddr */
1231558Srgrimes		(void *v, struct radix_node_head *head);
1241558Srgrimes	struct	radix_node *(*rnh_lookup)	/*exact match for sockaddr*/
1251558Srgrimes		(void *v, void *mask, struct radix_node_head *head);
1261558Srgrimes	struct	radix_node *(*rnh_matchpkt)	/* locate based on packet hdr */
1271558Srgrimes		(void *v, struct radix_node_head *head);
1281558Srgrimes	int	(*rnh_walktree)			/* traverse tree */
1291558Srgrimes		(struct radix_node_head *head, walktree_f_t *f, void *w);
1301558Srgrimes	int	(*rnh_walktree_from)		/* traverse tree below a */
1311558Srgrimes		(struct radix_node_head *head, void *a, void *m,
13298542Smckusick		     walktree_f_t *f, void *w);
1331558Srgrimes	void	(*rnh_close)	/* do something when the last ref drops */
1341558Srgrimes		(struct radix_node *rn, struct radix_node_head *head);
1351558Srgrimes	struct	radix_node rnh_nodes[3];	/* empty tree for common case */
1361558Srgrimes#ifdef _KERNEL
1371558Srgrimes	struct	rwlock rnh_lock;		/* locks entire radix tree */
13898542Smckusick#endif
1391558Srgrimes	struct	radix_node_head *rnh_masks;	/* Storage for our masks */
1401558Srgrimes};
1411558Srgrimes
1421558Srgrimes#ifndef _KERNEL
1431558Srgrimes#define R_Malloc(p, t, n) (p = (t) malloc((unsigned int)(n)))
1441558Srgrimes#define R_Zalloc(p, t, n) (p = (t) calloc(1,(unsigned int)(n)))
1451558Srgrimes#define Free(p) free((char *)p);
146102231Strhodes#else
1471558Srgrimes#define R_Malloc(p, t, n) (p = (t) malloc((unsigned long)(n), M_RTABLE, M_NOWAIT))
148102231Strhodes#define R_Zalloc(p, t, n) (p = (t) malloc((unsigned long)(n), M_RTABLE, M_NOWAIT | M_ZERO))
1491558Srgrimes#define Free(p) free((caddr_t)p, M_RTABLE);
1501558Srgrimes
15192837Simp#define	RADIX_NODE_HEAD_LOCK_INIT(rnh)	\
1521558Srgrimes    rw_init_flags(&(rnh)->rnh_lock, "radix node head", 0)
153107541Smckusick#define	RADIX_NODE_HEAD_LOCK(rnh)	rw_wlock(&(rnh)->rnh_lock)
154107541Smckusick#define	RADIX_NODE_HEAD_UNLOCK(rnh)	rw_wunlock(&(rnh)->rnh_lock)
155107541Smckusick#define	RADIX_NODE_HEAD_RLOCK(rnh)	rw_rlock(&(rnh)->rnh_lock)
156107541Smckusick#define	RADIX_NODE_HEAD_RUNLOCK(rnh)	rw_runlock(&(rnh)->rnh_lock)
15786473Siedowse#define	RADIX_NODE_HEAD_LOCK_TRY_UPGRADE(rnh)	rw_try_upgrade(&(rnh)->rnh_lock)
158145794Sdelphij
1591558Srgrimes
160107541Smckusick#define	RADIX_NODE_HEAD_DESTROY(rnh)	rw_destroy(&(rnh)->rnh_lock)
161107541Smckusick#define	RADIX_NODE_HEAD_LOCK_ASSERT(rnh) rw_assert(&(rnh)->rnh_lock, RA_LOCKED)
162107541Smckusick#define	RADIX_NODE_HEAD_WLOCK_ASSERT(rnh) rw_assert(&(rnh)->rnh_lock, RA_WLOCKED)
163107541Smckusick#endif /* _KERNEL */
164107541Smckusick
165107541Smckusickvoid	 rn_init(int);
166107541Smckusickint	 rn_inithead(void **, int);
167107541Smckusickint	 rn_detachhead(void **);
168107541Smckusickint	 rn_refines(void *, void *);
169107541Smckusickstruct radix_node
17073375Sobrien	 *rn_addmask(void *, int, int),
171107541Smckusick	 *rn_addmask_r(void *, struct radix_node_head *, int, int),
172107541Smckusick	 *rn_addroute (void *, void *, struct radix_node_head *,
173107541Smckusick			struct radix_node [2]),
174107541Smckusick	 *rn_delete(void *, void *, struct radix_node_head *),
175107541Smckusick	 *rn_lookup (void *v_arg, void *m_arg,
17673375Sobrien		        struct radix_node_head *head),
177107541Smckusick	 *rn_match(void *, struct radix_node_head *);
178107541Smckusick
179107541Smckusick#endif /* _RADIX_H_ */
180107541Smckusick