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

📄 routing_table.c

📁 aodv协议的实现 使用linux环境下的c++编写
💻 C
字号:
/***************************************************************************** * * Copyright (C) 2001 Uppsala University and Ericsson AB. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * * Authors: Erik Nordstr鰉, <erik.nordstrom@it.uu.se> * *****************************************************************************/#include <time.h>#ifdef NS_PORT#include "aodv-uu.h"#else#include "routing_table.h"#include "aodv_timeout.h"#include "packet_queue.h"#include "aodv_rerr.h"#include "aodv_hello.h"#include "aodv_socket.h"#include "k_route.h"#include "timer_queue.h"#include "defs.h"#include "debug.h"#include "params.h"#include "seek_list.h"#endif				/* NS_PORT */static unsigned int hashing(struct in_addr *addr, hash_value *hash);void NS_CLASS rt_table_init(){    int i;    rt_tbl.num_entries = 0;    rt_tbl.num_active = 0;    /* We do a for loop here... NS does not like us to use memset() */    for (i = 0; i < RT_TABLESIZE; i++) {	INIT_LIST_HEAD(&rt_tbl.tbl[i]);    }}void NS_CLASS rt_table_destroy(){    int i;    list_t *tmp = NULL, *pos = NULL;    for (i = 0; i < RT_TABLESIZE; i++) {	list_foreach_safe(pos, tmp, &rt_tbl.tbl[i]) {	    rt_table_t *rt = (rt_table_t *)pos;	    	    rt_table_delete(rt);	}    }}/* Calculate a hash value and table index given a key... */unsigned int hashing(struct in_addr * addr, hash_value * hash){    /*   *hash = (*addr & 0x7fffffff); */    *hash = (hash_value)addr->s_addr;    return (*hash & RT_TABLEMASK);}rt_table_t *NS_CLASS rt_table_insert(struct in_addr dest_addr, 				     struct in_addr next,				     u_int8_t hops, u_int32_t seqno,				     u_int32_t life, u_int8_t state,				     u_int16_t flags, unsigned int ifindex){    hash_value hash;    unsigned int index;    list_t *pos;    rt_table_t *rt;    struct in_addr nm;    nm.s_addr = 0;        /* Calculate hash key */    index = hashing(&dest_addr, &hash);    /* Check if we already have an entry for dest_addr */    list_foreach(pos, &rt_tbl.tbl[index]) {	rt = (rt_table_t *)pos;	if (memcmp(&rt->dest_addr, &dest_addr, sizeof(struct in_addr)) == 0) {	    DEBUG(LOG_INFO, 0, "%s already exist in routing table!", 		  ip_to_str(dest_addr));	    return NULL;	}    }    if ((rt = (rt_table_t *) malloc(sizeof(rt_table_t))) == NULL) {	fprintf(stderr, "Malloc failed!\n");	exit(-1);    }        memset(rt, 0, sizeof(rt_table_t));    rt->dest_addr = dest_addr;    rt->next_hop = next;    rt->dest_seqno = seqno;    rt->flags = flags;    rt->hcnt = hops;    rt->ifindex = ifindex;    rt->hash = hash;    rt->state = state;    timer_init(&rt->rt_timer, &NS_CLASS route_expire_timeout, rt);    timer_init(&rt->ack_timer, &NS_CLASS rrep_ack_timeout, rt);    timer_init(&rt->hello_timer, &NS_CLASS hello_timeout, rt);    rt->last_hello_time.tv_sec = 0;    rt->last_hello_time.tv_usec = 0;    rt->hello_cnt = 0;    rt->nprec = 0;    INIT_LIST_HEAD(&rt->precursors);    /* Insert first in bucket... */        rt_tbl.num_entries++;        DEBUG(LOG_INFO, 0, "Inserting %s (bucket %d) next hop %s",	  ip_to_str(dest_addr), index, ip_to_str(next));    list_add(&rt_tbl.tbl[index], &rt->l);        if (state == INVALID) {	if (flags & RT_REPAIR) {	    rt->rt_timer.handler = &NS_CLASS local_repair_timeout;	    life = ACTIVE_ROUTE_TIMEOUT;	} else {	    rt->rt_timer.handler = &NS_CLASS route_delete_timeout;	    life = DELETE_PERIOD;	}    } else {	rt_tbl.num_active++;#ifndef NS_PORT	/* Add route to kernel routing table ... */	if (k_add_rte(dest_addr, next, nm, hops, rt->ifindex) < 0)	    alog(LOG_WARNING, errno, __FUNCTION__,		"Could not add kernel route!");#endif    }#ifdef CONFIG_GATEWAY_DISABLE    if (rt->flags & RT_GATEWAY)	rt_table_update_inet_rt(rt, life);#endif    DEBUG(LOG_INFO, 0, "New timer for %s, life=%d",	  ip_to_str(rt->dest_addr), life);    if (life != 0)	timer_set_timeout(&rt->rt_timer, life);    /* In case there are buffered packets for this destination, we     * send them on the new route. */    if (rt->state == VALID && seek_list_remove(seek_list_find(dest_addr))) {	if (rt->flags & RT_INET_DEST)            packet_queue_set_verdict(dest_addr, PQ_ENC_SEND);        else            packet_queue_set_verdict(dest_addr, PQ_SEND);    }    return rt;}rt_table_t *NS_CLASS rt_table_update(rt_table_t * rt, struct in_addr next,				     u_int8_t hops, u_int32_t seqno,				     u_int32_t lifetime, u_int8_t state,				     u_int16_t flags){    struct in_addr nm;    nm.s_addr = 0;    if (rt->state == INVALID && state == VALID) {	/* If this previously was an expired route, but will now be	   active again we must add it to the kernel routing	   table... */	rt_tbl.num_active++;#ifndef NS_PORT	if (k_add_rte(rt->dest_addr, next, nm, hops, rt->ifindex) < 0)	    alog(LOG_WARNING, errno, __FUNCTION__,		"Could not add kernel route!");	else	    DEBUG(LOG_INFO, 0, "Added kernel route for expired %s",		  ip_to_str(rt->dest_addr));#endif    } else if (rt->next_hop.s_addr != 0 && 	       rt->next_hop.s_addr != next.s_addr) {	DEBUG(LOG_INFO, 0, "rt->next_hop=%s, new_next_hop=%s",	      ip_to_str(rt->next_hop), ip_to_str(next));#ifndef NS_PORT	if (k_chg_rte(rt->dest_addr, next, nm, hops, rt->ifindex) < 0)	    alog(LOG_WARNING, errno, __FUNCTION__,		"Could not update kernel route!");#endif    }    rt->dest_seqno = seqno;    rt->flags = flags;    rt->next_hop = next;    if (hops > 1 && rt->hcnt == 1) {	rt->last_hello_time.tv_sec = 0;	rt->last_hello_time.tv_usec = 0;	rt->hello_cnt = 0;	timer_remove(&rt->hello_timer);    }    rt->hcnt = hops;    /* Finally, mark as VALID */    rt->state = state;    #ifdef CONFIG_GATEWAY_DISABLED    if (rt->flags & RT_GATEWAY)	rt_table_update_inet_rt(rt, lifetime);#endif    rt->rt_timer.handler = &NS_CLASS route_expire_timeout;    rt_table_update_timeout(rt, lifetime);            /* In case there are buffered packets for this destination, we send     * them on the new route. */    if (rt->state == VALID && seek_list_remove(seek_list_find(rt->dest_addr))) {	if (rt->flags & RT_INET_DEST)            packet_queue_set_verdict(rt->dest_addr, PQ_ENC_SEND);        else            packet_queue_set_verdict(rt->dest_addr, PQ_SEND);    }    return rt;}NS_INLINE rt_table_t *NS_CLASS rt_table_update_timeout(rt_table_t * rt,						       u_int32_t lifetime){    struct timeval new_timeout;    if (!rt)	return NULL;    if (rt->state == VALID) {	/* Check if the current valid timeout is larger than the new	   one - in that case keep the old one. */	gettimeofday(&new_timeout, NULL);	timeval_add_msec(&new_timeout, lifetime);	if (timeval_diff(&rt->rt_timer.timeout, &new_timeout) < 0)	    timer_set_timeout(&rt->rt_timer, lifetime);    } else	timer_set_timeout(&rt->rt_timer, lifetime);    return rt;}rt_table_t *NS_CLASS rt_table_find(struct in_addr dest_addr){    hash_value hash;    unsigned int index;    list_t *pos;    if (rt_tbl.num_entries == 0)	return NULL;    /* Calculate index */    index = hashing(&dest_addr, &hash);    /* Handle collisions: */    list_foreach(pos, &rt_tbl.tbl[index]) {	rt_table_t *rt = (rt_table_t *)pos;	if (rt->hash != hash) 	    continue;		if (memcmp(&dest_addr, &rt->dest_addr, sizeof(struct in_addr)) == 0)	    return rt;    }    return NULL;}rt_table_t *NS_CLASS rt_table_find_gateway(){    rt_table_t *gw = NULL;    int i;    for (i = 0; i < RT_TABLESIZE; i++) {	list_t *pos;	list_foreach(pos, &rt_tbl.tbl[i]) {	    rt_table_t *rt = (rt_table_t *)pos;	    	    if (rt->flags & RT_GATEWAY && rt->state == VALID) {		if (!gw || rt->hcnt < gw->hcnt)		    gw = rt;	    }	}    }    return gw;}#ifdef CONFIG_GATEWAY_DISABLEDint NS_CLASS rt_table_update_inet_rt(rt_table_t *gw, u_int32_t life){    int n = 0;    int i;        if (!gw)	return -1;    for (i = 0; i < RT_TABLESIZE; i++) {	list_t *pos;	list_foreach(pos, &rt_tbl.tbl[i]) {	    rt_table_t *rt = (rt_table_t *)pos;	    	    if (rt->flags & RT_INET_DEST && rt->state == INVALID) {		rt_table_update(rt, gw->dest_addr, gw->hcnt, 0, life,				VALID, rt->flags);		n++;	    }	}    }    return n;}#endif /* CONFIG_GATEWAY_DISABLED *//* Route expiry and Deletion. */int NS_CLASS rt_table_invalidate(rt_table_t * rt){    struct timeval now;    gettimeofday(&now, NULL);    if (rt == NULL)	return -1;     /* If the route is already invalidated, do nothing... */    if (rt->state == INVALID) {	DEBUG(LOG_DEBUG, 0, "Route %s already invalidated!!!",	      ip_to_str(rt->dest_addr));	return -1;    }        if (rt->hello_timer.used) {	DEBUG(LOG_DEBUG, 0, "last HELLO: %ld",	      timeval_diff(&now, &rt->last_hello_time));    }       /* Remove any pending, but now obsolete timers. */    timer_remove(&rt->rt_timer);    timer_remove(&rt->hello_timer);    timer_remove(&rt->ack_timer);    /* Mark the route as invalid */    rt->state = INVALID;    rt_tbl.num_active--;    rt->hello_cnt = 0;    /* When the lifetime of a route entry expires, increase the sequence       number for that entry. */    seqno_incr(rt->dest_seqno);        rt->last_hello_time.tv_sec = 0;    rt->last_hello_time.tv_usec = 0;#ifndef NS_PORT    /* Delete kernel routing table entry. */    if (k_del_rte(rt->dest_addr) < 0)	alog(LOG_WARNING, errno, __FUNCTION__, "Could not delete kernel route!");#endif    #ifdef CONFIG_GATEWAY    /* If this was a gateway, check if any Internet destinations were using     * it. In that case update them to use a backup gateway or invalide them     * too. */    if (rt->flags & RT_GATEWAY) {	int i;		rt_table_t *gw = rt_table_find_gateway();		for (i = 0; i < RT_TABLESIZE; i++) {	    list_t *pos;	    list_foreach(pos, &rt_tbl.tbl[i]) {		rt_table_t *rt2 = (rt_table_t *)pos;				if (rt2->state == VALID && (rt2->flags & RT_INET_DEST) &&		    (rt2->next_hop.s_addr == rt->dest_addr.s_addr)) {		    if (0) {			DEBUG(LOG_DEBUG, 0, "Invalidated GW %s but found new GW %s for %s",  ip_to_str(rt->dest_addr), ip_to_str(gw->dest_addr),  			      ip_to_str(rt2->dest_addr));			rt_table_update(rt2, gw->dest_addr, gw->hcnt, 0, 					timeval_diff(&rt->rt_timer.timeout, 						     &now), VALID, rt2->flags);		    } else {			rt_table_invalidate(rt2);			precursor_list_destroy(rt2);		    }		}	    }	}    }#endif    if (rt->flags & RT_REPAIR) {	/* Set a timeout for the repair */	rt->rt_timer.handler = &NS_CLASS local_repair_timeout;	timer_set_timeout(&rt->rt_timer, ACTIVE_ROUTE_TIMEOUT);	DEBUG(LOG_DEBUG, 0, "%s kept for repairs during %u msecs",	      ip_to_str(rt->dest_addr), ACTIVE_ROUTE_TIMEOUT);    } else {	/* Schedule a deletion timer */	rt->rt_timer.handler = &NS_CLASS route_delete_timeout;	timer_set_timeout(&rt->rt_timer, DELETE_PERIOD);	DEBUG(LOG_DEBUG, 0, "%s removed in %u msecs",	      ip_to_str(rt->dest_addr), DELETE_PERIOD);    }    return 0;}void NS_CLASS rt_table_delete(rt_table_t *rt){    if(!rt) {	DEBUG(LOG_ERR, 0, "No route entry to delete");	return;    }        list_detach(&rt->l);        precursor_list_destroy(rt);        if (rt->state == VALID) {	#ifndef NS_PORT	if (k_del_rte(rt->dest_addr) < 0)	    alog(LOG_WARNING, errno, __FUNCTION__,		"Could not delete kernel route!");	#endif	rt_tbl.num_active--;    }    /* Make sure timers are removed... */    timer_remove(&rt->rt_timer);    timer_remove(&rt->hello_timer);    timer_remove(&rt->ack_timer);        rt_tbl.num_entries--;        free(rt);    return;}/****************************************************************//* Add an neighbor to the active neighbor list. */void NS_CLASS precursor_add(rt_table_t * rt, struct in_addr addr){    precursor_t *pr;    list_t *pos;    /* Sanity check */    if (!rt)	return;    /* Check if the node is already in the precursors list. */    list_foreach(pos, &rt->precursors) {	pr = (precursor_t *)pos;	    	if (pr->neighbor.s_addr == addr.s_addr)	    return;    }        if ((pr = (precursor_t *) malloc(sizeof(precursor_t))) == NULL) {	perror("Could not allocate memory for precursor node!!\n");	exit(-1);    }    DEBUG(LOG_INFO, 0, "Adding precursor %s to rte %s",	  ip_to_str(addr), ip_to_str(rt->dest_addr));        pr->neighbor.s_addr = addr.s_addr;        /* Insert in precursors list */        list_add(&rt->precursors, &pr->l);    rt->nprec++;    return;}/****************************************************************//* Remove a neighbor from the active neighbor list. */void NS_CLASS precursor_remove(rt_table_t * rt, struct in_addr addr){    list_t *pos;    /* Sanity check */    if (!rt)	return;    list_foreach(pos, &rt->precursors) {	precursor_t *pr = (precursor_t *)pos;	if (pr->neighbor.s_addr == addr.s_addr) {	    DEBUG(LOG_INFO, 0, "Removing precursor %s from rte %s",		  ip_to_str(addr), ip_to_str(rt->dest_addr));	    list_detach(pos);	    rt->nprec--;	    free(pr);	    return;	}    }}/****************************************************************//* Delete all entries from the active neighbor list. */void precursor_list_destroy(rt_table_t * rt){    list_t *pos, *tmp;        /* Sanity check */    if (!rt)	return;    list_foreach_safe(pos, tmp, &rt->precursors) {	precursor_t *pr = (precursor_t *)pos;	list_detach(pos);	rt->nprec--;	free(pr);    }}

⌨️ 快捷键说明

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