00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "aodv.h"
00033
00034 aodv_table_entry_t*
00035 aodv_get_route( aodv_state_t* state,
00036 const aodv_addr_t* source,
00037 const aodv_addr_t* destination,
00038 int* ecode )
00039 {
00040 unsigned char have_ecode = 0;
00041 unsigned char need_rreq = 0;
00042 aodv_table_entry_t* retval = NULL;
00043 aodv_rreq_t* crreq;
00044 struct timeval* tv;
00045 unsigned long timeout;
00046
00047 if ( NULL != ecode )
00048 {
00049 have_ecode = 1;
00050 *ecode = AODV_GR_OK;
00051 }
00052
00053 if ( NULL == state )
00054 {
00055 if ( have_ecode ) *ecode = AODV_GR_NULLSTATE;
00056 return NULL;
00057 }
00058
00059 retval = aodv_lookup( &(state->routing_table), destination );
00060 if ( NULL != retval )
00061 {
00062 if ( aodv_table_entry_is_expired( retval ) )
00063 {
00064 if ( retval->valid_route )
00065 {
00066 retval->valid_route = 0;
00067 aodv_incr_seq_base( &(retval->dest_seq) );
00068 }
00069 else
00070 {
00071 remove_aodv_table_entry( &(state->routing_table), retval );
00072 retval = NULL;
00073 }
00074 }
00075 else
00076 {
00077 if ( retval->valid_route )
00078 {
00079 aodv_update_route_expiry( state, retval );
00080 return retval;
00081 }
00082 else
00083 {
00084 aodv_update_invalid_route_lifetime( state, retval );
00085 }
00086 }
00087 }
00088
00089 if ( ( 0 != aodv_cmp_addr( source, &(state->self) ) ) &&
00090 ( ( NULL == retval ) ||
00091 ( ! retval->valid_route ) ) )
00092 {
00093 aodv_rerr_t rerr;
00094 rerr.dest_count = 1;
00095 rerr.unreachable = 0;
00096 uint32_t seq = 0;
00097 if ( 0 != retval )
00098 {
00099 seq = retval->dest_seq;
00100 }
00101 aodv_add_to_node_list( &(rerr.unreachable), destination, seq );
00102 if ( aodv_insert_time( state->rerr_time_ring ) )
00103 {
00104 aodv_bcast_rerr( state, &rerr );
00105 }
00106 if ( have_ecode ) *ecode = AODV_GR_NOROUTE;
00107 return NULL;
00108 }
00109
00110 need_rreq = 1;
00111
00112 crreq = state->rreq_buffer;
00113 if ( NULL != crreq )
00114 {
00115 do
00116 {
00117 if ( 0 == aodv_cmp_addr( &(crreq->destination), destination ) )
00118 {
00119 need_rreq = 0;
00120 if ( aodv_pasttime( &(crreq->buffer_time) ) )
00121 {
00122 if ( crreq->ntries < state->params.rreq_tries )
00123 {
00124 if ( aodv_insert_time( state->rreq_time_ring ) )
00125 {
00126 timeout =
00127 ( 1 << crreq->ntries ) *
00128 state->params.net_traversal_time;
00129 (crreq->ntries)++;
00130 crreq->rreq_id = aodv_incr_rreq_id(state);
00131 tv = &(crreq->buffer_time);
00132 aodv_gettime(tv);
00133 tv->tv_usec += 1000 * timeout;
00134 while ( tv->tv_usec >= 1000000 )
00135 {
00136 tv->tv_usec -= 1000000;
00137 tv->tv_sec += 1;
00138 }
00139 aodv_bcast_rreq( state, crreq );
00140 if ( have_ecode ) *ecode = AODV_GR_PENDING;
00141 return NULL;
00142 }
00143 }
00144 else
00145 {
00146 if ( have_ecode ) *ecode = AODV_GR_NOROUTE;
00147 unbuffer_aodv_rreq( state, crreq );
00148 return NULL;
00149 }
00150 }
00151 if ( have_ecode ) *ecode = AODV_GR_PENDING;
00152 return NULL;
00153 }
00154 crreq = crreq->next;
00155 } while ( need_rreq && ( crreq != state->rreq_buffer ) );
00156 }
00157
00158 if ( have_ecode ) *ecode = AODV_GR_PENDING;
00159
00160 if ( need_rreq )
00161 {
00162 if ( ! aodv_generate_rreq( state, destination ) )
00163 {
00164 if ( have_ecode ) *ecode = AODV_GR_ERROR;
00165 }
00166 }
00167
00168 return NULL;
00169 }
00170