rripfdb.c

来自「用于嵌入式系统的TCP/IP协议栈及若干服务」· C语言 代码 · 共 2,850 行 · 第 1/5 页

C
2,850
字号
/**            Copyright (c) 1998-2001 by NETsilicon Inc.**  This software is copyrighted by and is the sole property of*  NETsilicon.  All rights, title, ownership, or other interests*  in the software remain the property of NETsilicon.  This*  software may only be used in accordance with the corresponding*  license agreement.  Any unauthorized use, duplication, transmission,*  distribution, or disclosure of this software is expressly forbidden.**  This Copyright notice may not be removed or modified without prior*  written consent of NETsilicon.**  NETsilicon, reserves the right to modify this software*  without notice.**  NETsilicon*  411 Waverley Oaks Road                  USA 781.647.1234*  Suite 227                               http://www.netsilicon.com*  Waltham, MA 02452                       AmericaSales@netsilicon.com***************************************************************************  $Name: Fusion 6.52 Fusion 6.51 $*  $Date: 2002/01/22 14:09:57 $*  $Source: M:/psisrc/routing/rrfdb/rcs/rripfdb.c $*  $Revision: 1.33 $*****************************************************************************************************************************************************  File Description: IP forwarding database. Overall architecture used:1 hash table for all routing tables of a given metric.The contents of hash table are pointers to a routingentry (iproute_entry). ***********************************************/#include "riproute.h"#include "ipport.h"#include "ipaccess.h"#include "icirc.h"#include "rrfwd.h"#ifdef OSPF_PROTOCOL#include "fnsospf.h"#endif#include "fns_str.h"#define IPRT_CONTAIN(d1,m1,d2,m2) ((m1>m2)?0:(d1==(d2&m1))?1:0)fnc_prot(int, ipRedistCheck,(iproute_ent_pt,REDIST_TMPL *,IPRT_REDIST *,int))fnc_prot(void, bgpAddExtRt,(ipna_pt,IPRT_REDIST *))fnc_prot(void, bgpModExtRt,(ipna_pt))fnc_prot(void, bgpDelExtRt,(ipna_pt))fnc_prot(void, bgpRouteModified,(ipna_pt,int))fnc_prot(void, ospfAddExtRt,(ipna_pt,rripa,int,int,int,int,rripa))fnc_prot(void, ospfDelExtRt,(ipna_pt,int,int,int))fnc_prot(void, IrIpAddExtRt,(ipna_pt,int,int,int,int,int))fnc_prot(void, IrIpDelExtRt,(ipna_pt,int,int,int,int))fnc_prot(static iproute_ent_pt, ipFindBestRt,(rripa))fnc_prot(void, ipRtArpDeref,(iproute_ent_pt))fnc_prot(iproute_ent_pt, ipFindRoute,(ipna_pt,int))fnc_prot(icirc_pt,ipCircFromId,(int))fnc_prot(iproute_ent_pt, ipAddRoute, (ipna_pt,rripa,int,int,int,rripa))fnc_prot(void, ipDelRoute,(iproute_ent_pt iprt))fnc_prot(void, ipStaticRtOn,(int))fnc_prot(void, ipStaticRtOff,(int))fnc_prot(iproute_ent_pt, ipAddRouteM, (ipna_pt,int,rripa *,int *,int,int,rripa,int))fnc_prot(void, ipReplaceRouteM,(iproute_ent_pt,int,rripa *,int *,int,rripa,int,int))fnc_prot(static iproute_ent_pt, ipFindRt, (ipna_pt))\fnc_prot(int , ip_rtKey, (ipna_pt))fnc_prot(arpent_pt, IpGetNextHop, (byte *,int *, int ))fnc_prot(icirc_pt, ipGetMatchAddr, (icirc_pt c, rripa next))INODE *i_node = (INODE *)0;int addrsIndex = 0;int totalAddrs = 0;rripa rteTbl_Addrs[2*IP_ROUTE_HASHES];	/* filled in when a route is											inserted into the table.											used by SNMP										 *//**************************************************IrIpRtInit:Initialize IP routing tables.**************************************************/void IrIpRtInit(){	int i,max;	iproute_ent_pt rblk,srt;     /* hashing tables */	/* alloc main node */	if( (i_node = (inode_pt)RR_MALLOC(sizeof(INODE))) == 0){		ASSERT(0,"ip: cant alloc main node");		return;	}	rrFillMem((char *)i_node,0,sizeof(INODE));#ifdef IP_USE_PTREE	/* mask lens we have routes for */	for(i = 0; i < 33;i++){		i_node->rn_rtmasks[i] = -1;		i_node->rn_rtl2m[i] = ipRtLen2Mask(i);	}#else	/* hashing tables */	if( (i_node->rn_rt_def= (iproute_ent_pt *)	  ipRouteAlloc(2*sizeof(iproute_ent_pt)*IP_ROUTE_HASHES))== 0){		ASSERT(0,"IPINIT");	}	rrFillMem(i_node->rn_rt_def,0,2*sizeof(iproute_ent_pt)*IP_ROUTE_HASHES);#endif	/* only alloc structs for other metrics if we will	   use them */	/* blocks of path entry structs,	   to allow decision to run	   without stopping forwarding */	/* may alloc smaller table size for non-default */	max = IP_DEF_ROUTE_BSZ;	if((rblk= (iproute_ent_pt)  		ipRouteAlloc(sizeof(iproute_ent)* max))== 0){		ASSERT(0,"IPINIT");	}	/* link each struct in free list */	for(i = 0, srt = rblk ;i < max; srt++, i++){		rrLink((dll_pt)srt,(dll_pt)&i_node->rn_rtfwd_def);	}	i_node->rn_def_blks = 1;	/*  For SNMP code. */	addrsIndex = 0;	totalAddrs = 0;	rrFillMem(rteTbl_Addrs,0,2*IP_ROUTE_HASHES*sizeof(rripa));}#ifndef IP_USE_PTREE/*****************************************************table structure:table is organized as a dual linked list where eachlink is a pointer to the first member of a balancedbinary tree. links are iprt_fwd and iprt_bwd. Eachtree consists of routes with the same ip mask. Longest masktrees are linked ahead of those with shorter masks.trees are linked using iprt_left, iprt_right and iprt_bwd.When a search comes to the end of a tree, (left/right = 0),it continues with the iprt_fwd member stored when enteringthe tree. If all entries have different masks,or USE_BTREE is false, this degenerates to a normallinked list. ******************************************************/fnc_prot(static iproute_ent *,findNode,(rripa,iproute_ent *))fnc_prot(static int,getTreeHeight,(iproute_ent *))fnc_prot(static int,ip_btinsert,(iproute_ent *,iproute_ent *,iproute_ent **,int))fnc_prot(static void,ip_btdelete,(iproute_ent *,iproute_ent *,iproute_ent **,int))/******************************************route insertion/deletion:use radix or binary tree function.returns 0 success, -1 failure******************************************/int ip_rtinsert(iproute_ent *iprt){	ipna_pt ipna = &iprt->iprt_ipa;	iproute_ent_pt tmp,*tbl;	int bin,rc;    use_critical;	/* Put address in SNMP table of addresses in routing table. */	if (addrsIndex != (2*IP_ROUTE_HASHES-1))	{		rteTbl_Addrs[addrsIndex++] = ipna->ip_add;		totalAddrs++;	}	else		addrsIndex = 0;	/* link it according to length of mask */	/* link according to subnet mask len, longest first */	/* anything with the same mask goes into a balanced	   binary tree.	*/	/* note: this is going into an active routing table, so	   we need to be careful and guarantee atomic pointer	   write	*/	bin = ip_rtKey(ipna);	tbl = i_node->rn_rt_def;	tmp= tbl[2*bin];	if(!tmp){		/* first in chain */		iprt->iprt_fwd = 0;		iprt->iprt_bwd = 0;		critical;		tbl[2*bin] = iprt;		tbl[2*bin +1] = iprt;		normal;#ifdef USE_BTREE		iprt->iprt_left = iprt->iprt_right = 0;		iprt->iprt_bal = 0;#endif		return(0);	}	/* find same mask or shorter */	else for(; tmp; tmp = tmp->iprt_fwd){			if(iprt->iprt_ipa.ip_mask > 			tmp->iprt_ipa.ip_mask){			/* new has longer mask than tmp, insert			   in front of tmp.			*/			iprt->iprt_fwd = tmp;			iprt->iprt_bwd = tmp->iprt_bwd;			if(iprt->iprt_bwd){				critical;				iprt->iprt_bwd->iprt_fwd = iprt;				tmp->iprt_bwd = iprt;				normal;			}			else{				critical;				tbl[2*bin] = iprt;				tmp->iprt_bwd = iprt;				normal;			}#ifdef USE_BTREE			iprt->iprt_left = iprt->iprt_right = 0;			iprt->iprt_bal = 0;#endif			return(0);		}		else if(iprt->iprt_ipa.ip_mask == 			tmp->iprt_ipa.ip_mask){			/* it has same mask, insert in tree */#ifdef USE_BTREE			critical;			rc = ip_btinsert(iprt,tmp,tbl,bin);			normal;#else			iprt->iprt_fwd = tmp;			iprt->iprt_bwd = tmp->iprt_bwd;			if(iprt->iprt_bwd){				critical;				iprt->iprt_bwd->iprt_fwd = iprt;				tmp->iprt_bwd = iprt;				normal;			}			else{				critical;				tbl[2*bin] = iprt;				tmp->iprt_bwd = iprt;				normal;			}			rc = 0;#endif			return(rc);		}	}	/* got to end of list, new has shortest mask */	iprt->iprt_fwd = 0;	iprt->iprt_bwd = tbl[2*bin+1];#ifdef USE_BTREE	iprt->iprt_left = iprt->iprt_right = 0;	iprt->iprt_bal = 0;#endif	critical;	iprt->iprt_bwd->iprt_fwd = iprt;	tbl[2*bin+1] = iprt;	normal;	return(0);}int ip_rtdelete(iproute_ent *iprt){	iproute_ent *tmp;	iproute_ent_pt *tbl;	int bin, i;    use_critical;	bin = ip_rtKey(&iprt->iprt_ipa);	tbl = i_node->rn_rt_def;	/* Remove from SNMP table of routes. */	for (i=0; i<2*IP_ROUTE_HASHES; i++)	{		if (rteTbl_Addrs[i] == iprt->iprt_ipa.ip_add)		{			rteTbl_Addrs[i] = (u32)0;			totalAddrs--;			break;		}	}#ifdef USE_BTREE	/* find out if we are in a tree, or standalone	   link element */	if( iprt->iprt_left || iprt->iprt_right ||		/* could be a tree leaf node */	   (iprt->iprt_bwd &&	    iprt->iprt_bwd->iprt_ipa.ip_mask == iprt->iprt_ipa.ip_mask)){		/* in tree, find tree head */		for(tmp = iprt; tmp; tmp = tmp->iprt_bwd){			if(!tmp->iprt_bwd ||			   tmp->iprt_bwd->iprt_ipa.ip_mask !=			   iprt->iprt_ipa.ip_mask ){				critical;				ip_btdelete(iprt,tmp,tbl,bin);				normal;				return(0);			}		}		ASSERT(0,"ip_rtdelete");	}#endif /* USE_BTREE */	/* standalone, just unlink */	critical;	if(iprt->iprt_fwd){		iprt->iprt_fwd->iprt_bwd = iprt->iprt_bwd;	}	else{		tbl[2*bin+1] = iprt->iprt_bwd;	}			if(iprt->iprt_bwd){		iprt->iprt_bwd->iprt_fwd = iprt->iprt_fwd;	}	else{		tbl[2*bin] = iprt->iprt_fwd;	}			normal;	return(0);}#ifdef USE_BTREE/* look at the back link from XN1 and set its left or   right fwd link to XN2*/#define ADJ_BLINK(XN1,XN2) {\if(XN1->iprt_bwd->iprt_left == XN1)            \	XN1->iprt_bwd->iprt_left = XN2;           \else                                           \	XN1->iprt_bwd->iprt_right = XN2;          \}/******************************************find route with next highest val, given head and current route********************************************/iproute_ent  *ip_btnext(iproute_ent *nd,iproute_ent *prev){	/* if there is right link, follow it then all left	   links.	*/	if(nd->iprt_right){		nd = nd->iprt_right;		for(;nd;nd = nd->iprt_left){			if(!nd->iprt_left)				return(nd);		}	}	/* go up tree till we find a link that is left	   (ie. up is greater)	*/	while(1){		if(nd->iprt_bwd == prev) return(0);		if(nd->iprt_bwd->iprt_left == nd)			return(nd->iprt_bwd);		nd = nd->iprt_bwd;	}}/******************************************find route with next highest val, givenhead and current route********************************************/iproute_ent  *ip_btfirst(iproute_ent *nd){	/* find first */	/* follow left links */	for(; ; nd = nd->iprt_left){		if(!nd->iprt_left)			break;	}	return(nd);}int ip_rtver(){	iproute_ent *nd,**tbl,*head,*tail;	int i,bl,br;	int errnox;	int saw_tail = 0;	tbl = i_node->rn_rt_def;	/* process each path entry */	for(i= 0; i< IP_ROUTE_HASHES; i++){		head = *(tbl +(2*i));		if(head && head->iprt_bwd){			errnox = 20;			goto puke;		}		tail = *(tbl +(2*i)+1);		if(tail && tail->iprt_fwd){			errnox = 21;			goto puke;		}		RT_BINWALK(nd,*(tbl+(2*i)))		if(nd == tail)saw_tail = 1;		/* ver fwd/back links */		if(nd->iprt_left && nd->iprt_left->iprt_bwd != nd){			errnox = 1;			goto puke;		}		if(nd->iprt_right && nd->iprt_right->iprt_bwd != nd){			errnox = 2;			goto puke;		}		/* check links, differ if head, vs tree internal */		if(nd->iprt_bwd && nd->iprt_bwd->iprt_ipa.ip_mask ==		    nd->iprt_ipa.ip_mask){			if(nd->iprt_bwd->iprt_left != nd &&			   nd->iprt_bwd->iprt_right != nd){				errnox = 3;				goto puke;			}		}		else{		  if(nd->iprt_fwd && nd->iprt_fwd->iprt_bwd != nd){			errnox = 4;			goto puke;		  }		  if(nd->iprt_bwd && nd->iprt_bwd->iprt_fwd != nd){			errnox = 5;			goto puke;		  }		}		/* ver add.ip_addues */		if(nd->iprt_left && nd->iprt_left->iprt_ipa.ip_add >= nd->iprt_ipa.ip_add){			errnox = 6;			goto puke;		}		if(nd->iprt_right && nd->iprt_right->iprt_ipa.ip_add <= nd->iprt_ipa.ip_add){			errnox = 7;			goto puke;		}		/* ver balance */		bl = getTreeHeight(nd->iprt_left);		br = getTreeHeight(nd->iprt_right);		if(bl -br >1 || br-bl > 1){			errnox = 8;			goto puke;		}		if(br -bl != nd->iprt_bal){			errnox = 9;			goto puke;		}		/* sanity (dont chk fwd)*/		if(nd->iprt_left == nd ||	 	   nd->iprt_right == nd ||		   nd->iprt_bwd == nd){			errnox = 10;			goto puke;		}		RT_BINWALKEND		if(tail && !saw_tail){			errnox = 22;			goto puke;		}	}	return(0);puke:	return(errnox);}/******************************************Given a route, return the next route.  Given anull route returns the head of the table.********************************************/rripa* ip_getRteTableAddrs(int* count){	int i;	rripa* rteAddrs;	*count = 0;	rteAddrs = (rripa*)h_alloc(totalAddrs * sizeof(rripa), &i, 1);	if (i)		return(NULL);	for (i=0; i < 2*IP_ROUTE_HASHES && *count < totalAddrs; i++)	{		if (rteTbl_Addrs[i])			rteAddrs[(*count)++] = rteTbl_Addrs[i];	}	return(rteAddrs);	}  /* end ip_getRteTableAddrs */static iproute_ent *findNode(rripa add,iproute_ent *head){	iproute_ent *nd = head;	while(nd){		if(nd->iprt_ipa.ip_add == add) return(nd);		else if(add > nd->iprt_ipa.ip_add) nd = nd->iprt_right;		else nd = nd->iprt_left;	}	return((iproute_ent *)0);}static int getTreeHeight(iproute_ent *nd){	int cnt = 0;	while(nd){		cnt++;		if(nd->iprt_bal < 0)			nd = nd->iprt_left;		else			nd = nd->iprt_right;	}	return(cnt);}static int ip_btinsert(iproute_ent *node,iproute_ent *head,iproute_ent **tbl,int bin){	rripa add = node->iprt_ipa.ip_add;	iproute_ent *tmp,*adjnd,*r;	int  a;	if(findNode(add,head))		 return(-1);	node->iprt_left = 0;	node->iprt_right = 0;	node->iprt_bwd = 0;	node->iprt_fwd = 0;	node->iprt_bal = 0;	node->iprt_ipa.ip_add = add;	/* find a home, will add at end of a chain */	tmp = head;	adjnd = head;

⌨️ 快捷键说明

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