⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 radix.c

📁 很好的一个嵌入式linux平台下的bootloader
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $Id: radix.c,v 1.2 1996/01/16 14:21:56 chris Exp $ *//* * Copyright (c) 1988, 1989  Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * *	@(#)radix.c	7.9 (Berkeley) 2/4/91 *//* * Routines to build and maintain radix trees for routing lookups. */#ifndef RNF_NORMAL#include "param.h"#include "radix.h"#include "malloc.h"#define	M_DONTWAIT M_NOWAIT#endifstruct radix_node_head *mask_rnhead;#define rn_maskhead mask_rnhead->rnh_treetopstruct radix_mask *rn_mkfreelist;struct radix_node_head *radix_node_head;#undef Bcmp#define Bcmp(a, b, l) (l == 0 ? 0 : bcmp((caddr_t)(a), (caddr_t)(b), (u_long)l))/* * The data structure for the keys is a radix tree with one way * branching removed.  The index rn_b at an internal node n represents a bit * position to be tested.  The tree is arranged so that all descendants * of a node n have keys whose bits all agree up to position rn_b - 1. * (We say the index of n is rn_b.) * * There is at least one descendant which has a one bit at position rn_b, * and at least one with a zero there. * * A route is determined by a pair of key and mask.  We require that the * bit-wise logical and of the key and mask to be the key. * We define the index of a route to associated with the mask to be * the first bit number in the mask where 0 occurs (with bit number 0 * representing the highest order bit). *  * We say a mask is normal if every bit is 0, past the index of the mask. * If a node n has a descendant (k, m) with index(m) == index(n) == rn_b, * and m is a normal mask, then the route applies to every descendant of n. * If the index(m) < rn_b, this implies the trailing last few bits of k * before bit b are all 0, (and hence consequently true of every descendant * of n), so the route applies to all descendants of the node as well. * * The present version of the code makes no use of normal routes, * but similar logic shows that a non-normal mask m such that * index(m) <= index(n) could potentially apply to many children of n. * Thus, for each non-host route, we attach its mask to a list at an internal * node as high in the tree as we can go.  */struct radix_node *rn_search(v, head)	struct radix_node *head;	register caddr_t v;{	register struct radix_node *x;	for (x = head; x->rn_b >= 0;) {		if (x->rn_bmask & v[x->rn_off])			x = x->rn_r;		else			x = x->rn_l;	}	return x;};struct radix_node *rn_search_m(v, head, m)	struct radix_node *head;	register caddr_t v, m;{	register struct radix_node *x;	for (x = head; x->rn_b >= 0;) {		if ((x->rn_bmask & m[x->rn_off]) &&		    (x->rn_bmask & v[x->rn_off]))			x = x->rn_r;		else			x = x->rn_l;	}	return x;};static int gotOddMasks;static char maskedKey[MAXKEYLEN];struct radix_node *rn_match(v, head)	struct radix_node *head;	caddr_t v;{	register struct radix_node *t = head, *x;	register caddr_t cp = v, cp2, cp3;	caddr_t cplim, mstart;	struct radix_node *saved_t;	int off = t->rn_off, vlen = *(u_char *)cp, matched_off;	/*	 * Open code rn_search(v, head) to avoid overhead of extra	 * subroutine call.	 */	for (; t->rn_b >= 0; ) {		if (t->rn_bmask & cp[t->rn_off])			t = t->rn_r;		else			t = t->rn_l;	}	/*	 * See if we match exactly as a host destination	 */	cp += off; cp2 = t->rn_key + off; cplim = v + vlen;	for (; cp < cplim; cp++, cp2++)		if (*cp != *cp2)			goto on1;	/*	 * This extra grot is in case we are explicitly asked	 * to look up the default.  Ugh!	 */	if ((t->rn_flags & RNF_ROOT) && t->rn_dupedkey)		t = t->rn_dupedkey;	return t;on1:	matched_off = cp - v;	saved_t = t;	do {	    if (t->rn_mask) {		/*		 * Even if we don't match exactly as a hosts;		 * we may match if the leaf we wound up at is		 * a route to a net.		 */		cp3 = matched_off + t->rn_mask;		cp2 = matched_off + t->rn_key;		for (; cp < cplim; cp++)			if ((*cp2++ ^ *cp) & *cp3++)				break;		if (cp == cplim)			return t;		cp = matched_off + v;	    }	} while (t = t->rn_dupedkey);	t = saved_t;	/* start searching up the tree */	do {		register struct radix_mask *m;		t = t->rn_p;		if (m = t->rn_mklist) {			/*			 * After doing measurements here, it may			 * turn out to be faster to open code			 * rn_search_m here instead of always			 * copying and masking.			 */			off = min(t->rn_off, matched_off);			mstart = maskedKey + off;			do {				cp2 = mstart;				cp3 = m->rm_mask + off;				for (cp = v + off; cp < cplim;)					*cp2++ =  *cp++ & *cp3++;				x = rn_search(maskedKey, t);				while (x && x->rn_mask != m->rm_mask)					x = x->rn_dupedkey;				if (x &&				    (Bcmp(mstart, x->rn_key + off,					vlen - off) == 0))					    return x;			} while (m = m->rm_mklist);		}	} while (t != head);	return 0;};		#ifdef RN_DEBUGint	rn_nodenum;struct	radix_node *rn_clist;int	rn_saveinfo;#endifstruct radix_node *rn_newpair(v, b, nodes)	caddr_t v;	struct radix_node nodes[2];{	register struct radix_node *tt = nodes, *t = tt + 1;	t->rn_b = b; t->rn_bmask = 0x80 >> (b & 7);	t->rn_l = tt; t->rn_off = b >> 3;	tt->rn_b = -1; tt->rn_key = v; tt->rn_p = t;	tt->rn_flags = t->rn_flags = RNF_ACTIVE;#ifdef RN_DEBUG	tt->rn_info = rn_nodenum++; t->rn_info = rn_nodenum++;	tt->rn_twin = t; tt->rn_ybro = rn_clist; rn_clist = tt;#endif	return t;}#ifdef RN_DEBUGint rn_debug =  1;#endifstruct radix_node *rn_insert(v, head, dupentry, nodes)	caddr_t v;	struct radix_node *head;	int *dupentry;	struct radix_node nodes[2];{	int head_off = head->rn_off, vlen = (int)*((u_char *)v);	register struct radix_node *t = rn_search(v, head);	register caddr_t cp = v + head_off;	register int b;	struct radix_node *tt;    	/*	 *find first bit at which v and t->rn_key differ	 */    {	register caddr_t cp2 = t->rn_key + head_off;	register int cmp_res;	caddr_t cplim = v + vlen;	while (cp < cplim)		if (*cp2++ != *cp++)			goto on1;	*dupentry = 1;	return t;on1:	*dupentry = 0;	cmp_res = (cp[-1] ^ cp2[-1]) & 0xff;	for (b = (cp - v) << 3; cmp_res; b--)		cmp_res >>= 1;    }    {	register struct radix_node *p, *x = head;	cp = v;	do {		p = x;		if (cp[x->rn_off] & x->rn_bmask) 			x = x->rn_r;		else x = x->rn_l;	} while (b > (unsigned) x->rn_b); /* x->rn_b < b && x->rn_b >= 0 */#ifdef RN_DEBUG	if (rn_debug)		printf("Going In:\n"), traverse(p);#endif	t = rn_newpair(v, b, nodes); tt = t->rn_l;	if ((cp[p->rn_off] & p->rn_bmask) == 0)		p->rn_l = t;	else		p->rn_r = t;	x->rn_p = t; t->rn_p = p; /* frees x, p as temp vars below */	if ((cp[t->rn_off] & t->rn_bmask) == 0) {		t->rn_r = x;	} else {		t->rn_r = tt; t->rn_l = x;	}#ifdef RN_DEBUG	if (rn_debug)		printf("Coming out:\n"), traverse(p);#endif    }	return (tt);}struct radix_node *rn_addmask(netmask, search, skip)caddr_t netmask;{	register struct radix_node *x;	register caddr_t cp, cplim;	register int b, mlen, j;	int maskduplicated;	mlen = *(u_char *)netmask;	if (search) {		x = rn_search(netmask, rn_maskhead);		mlen = *(u_char *)netmask;		if (Bcmp(netmask, x->rn_key, mlen) == 0)			return (x);	}	R_Malloc(x, struct radix_node *, MAXKEYLEN + 2 * sizeof (*x));	if (x == 0)		return (0);	Bzero(x, MAXKEYLEN + 2 * sizeof (*x));	cp = (caddr_t)(x + 2);	Bcopy(netmask, cp, mlen);	netmask = cp;	x = rn_insert(netmask, rn_maskhead, &maskduplicated, x);	/*	 * Calculate index of mask.	 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -