📄 dsr_routing_layer.pr.c
字号:
}
while ((reply_route.route[i]!=my_dsr_address)&&(i<reply_route.size_route));
// if the node is still there: it was not in a loop and the reply packet can be sent
if (i<reply_route.size_route)
{
// assign the first relay on the reply packet's route
relay_dsr_address=reply_route.route[i-1];
// set the Seg_Left field of the reply
seg_left=i-1;
op_pk_nfd_set(reply_pk_ptr,"IP_TTL",seg_left);
if (DEBUG != 0)
{
printf("Reply from Relay route with seg_left=%d: ",seg_left);
printf("%d...",request_source_dsr_address);
}
// copy the reply_route in the Node_i fields of the packet
for (i=1;i<reply_route.size_route;i++)
{
if (DEBUG != 0)
{
printf("%d...",reply_route.route[i]);
}
sprintf(field,"Node_%d",i-1);
op_pk_nfd_set(reply_pk_ptr,field,reply_route.route[i]);
}
if (DEBUG != 0)
{
printf("end\n");
}
// set the Opt_Data_Len field of the reply = size_route minus source node
op_pk_nfd_set(reply_pk_ptr,"Opt_Data_Len",reply_route.size_route-1);
// set the TR_source field for the Transmission range purpose
op_pk_nfd_set(reply_pk_ptr,"TR_source",my_node_objid);
// since I am the reply transmitter I will not have to process it in the future
//dsr_reply_already_seen(my_dsr_address,request_source_dsr_address,sequence_number);
dsr_reply_already_seen(request_source_dsr_address,request_destination_dsr_address,sequence_number);
// init the delay_reply distribution
delay_reply_dist=op_dist_load("uniform",0.0,1.0);
// calculate the delay that the node must wait before sending its reply
delay=op_dist_outcome(delay_reply_dist);
delay=HOP_DELAY*((double)(reply_route.size_route-2)+delay);
// prepare the code (destination and source coded in one integer) associated (in the fifo) with the reply information
intPtr=(int*)op_prg_mem_alloc(sizeof(int));
*intPtr=request_destination_dsr_address*OPTION+request_source_dsr_address;
// check if a reply for the same route is still scheduled by looking in the fifo for its information
reply=fifo_multiplex_extract(&reply_fifo,*intPtr);
// if some information about a scheduled reply are found
if (reply!=NULL)
{
// cancel the intrpt associated with this previous scheduled reply
if (complex_intrpt_cancel(my_complex_intrpt_ptr,reply->evt))
{
// "replies" statistic calculation if success
++total_canceled_replies;
op_stat_write(stat_total_canceled_replies,total_canceled_replies);
}
else
{
// error since the intrpt must be valid and active
op_sim_end("Amazing error: reply should be valid and active","","","");
}
// destroy the information about this reply
op_pk_destroy(reply->pk);
op_prg_mem_free(reply);
}
// memory allocation for structure containing information about the new reply
reply=(sReply*)op_prg_mem_alloc(sizeof(sReply));
// store in it the reply packet
reply->pk=reply_pk_ptr;
// and its sequence number
reply->sequence_number=sequence_number;
// schedule an intrpt that will "say" when to send the reply and store the associated event in the reply information structure
reply->evt=complex_intrpt_schedule_self(my_complex_intrpt_ptr,op_sim_time()+delay,SEND_REPLY_CODE,intPtr);
// save the scheduled reply in a multiplexed Fifo
fifo_multiplex_insert(&reply_fifo,reply,*intPtr);
sprintf(message,"I plan to send a reply to %d for the route reaching %d in %f seconds (size_route=%d)\n",request_source_dsr_address,request_destination_dsr_address,delay,reply_route.size_route);
dsr_message(message);
}
// if the current node was in a loop, its dsr address is not the reply_route anymore so the packet can't be sent back to the request source
else
{
dsr_message("Proper route not found\n");
// Check all cached routes to this destination for nodes in the request packet's route thus far
// If any are found, then those nodes can no longer be used to reach this destination
for (i=0; i<MAX_CACHED_ROUTES; i++)
{
j = 0;
node_found = 0;
do
{
if (route_cache[request_destination_dsr_address].node_route[i].route[j]==request_source_dsr_address)
{
dsr_route_init(route_cache,request_destination_dsr_address,i);
node_found = 1;
}
j++;
}
while (j<MAX_SIZE_ROUTE && node_found == 0);
}
dsr_swap_route(route_cache,request_destination_dsr_address);
op_pk_destroy(reply_pk_ptr);
return (0);
}
}
// destroy the request packet
op_pk_destroy(pk_ptr);
// breakpoints for debugging purpose
if (1)
{
op_prg_odb_bkpt("transmit_reply");
op_prg_odb_bkpt("transmit_reply_from_relay");
}
return (1);
}
/*************************************************************/
/* DSR_HANDLE_REPLY */
/*************************************************************/
/* This function handle any reply packet received by the node*/
/* */
/* Packet* pk_ptr: a pointer to the reply packet to process */
/*************************************************************/
void dsr_handle_reply(Packet* pk_ptr)
{
int reply_source_dsr_address;
int destination_dsr_address;
int sequence_number;
int intended_relay_dsr_address;
int route_source_dsr_address;
int route_destination_dsr_address;
int size_route;
int seg_left;
int node_dsr_address;
int current_node_index;
Packet* data_pk_ptr;
int from_target;
char field[10];
int i;
char message[255];
int error_in_relay_reply_route;
// extract usefull information from the reply packet
op_pk_nfd_get (pk_ptr,"SRC",&reply_source_dsr_address);
op_pk_nfd_get (pk_ptr,"DEST",&route_source_dsr_address);
op_pk_nfd_get (pk_ptr,"Identification",&sequence_number);
op_pk_nfd_get (pk_ptr,"Reply_From_Target",&from_target);
op_pk_nfd_get(pk_ptr,"Opt_Data_Len",&size_route);
// add source node to size_route
size_route = size_route + 1;
sprintf(field,"Node_%d",size_route - 2);
op_pk_nfd_get (pk_ptr,field,&route_destination_dsr_address);
op_pk_nfd_get(pk_ptr,"IP_TTL",&seg_left);
// obtain the address of the intended relay node
if (seg_left > 0)
{
sprintf(field,"Node_%d",seg_left-1);
op_pk_nfd_get(pk_ptr,field,&intended_relay_dsr_address);
}
else
{
intended_relay_dsr_address = route_source_dsr_address;
}
if (DEBUG > 0)
{
sprintf(message,"Relay address for Reply packet from node %d with seq# %d back to %d = %d\n",
reply_source_dsr_address,sequence_number,route_source_dsr_address,intended_relay_dsr_address);
dsr_message(message);
}
// Check if I am the intended reply relay node or the destination of the reply packet
if (my_dsr_address == route_source_dsr_address || my_dsr_address == intended_relay_dsr_address)
{
dsr_insert_reply_route_in_cache(pk_ptr);
}
// Check to see if this reply packet has already been seen
if (((!dsr_reply_already_seen(route_source_dsr_address,route_destination_dsr_address,sequence_number))||
(sequence_number==-1)))
{
// if the reply packet is destinated to the current node
if (my_dsr_address==route_source_dsr_address)
{
if (request_sent[route_destination_dsr_address].waiting_time!=0)
{
// cancel the intrpt associated with this request expiration time
//if (complex_intrpt_cancel(my_complex_intrpt_ptr,request_sent[source_dsr_address].evt))
if (complex_intrpt_cancel(my_complex_intrpt_ptr,request_sent[route_destination_dsr_address].evt))
{
//printf("well done for the path !\n");
// re-init the request_sent table since the reply has been received
request_sent[route_destination_dsr_address].scheduling_time = 0.0;
request_sent[route_destination_dsr_address].waiting_time = 0.0;
request_sent[route_destination_dsr_address].sequence_number = -1;
}
else
{
// error since the intrpt must be valid and active
op_sim_end("Amazing error: request intrpt should be valid and active","","","");
op_stat_write(stat_amazing_errors,++amazing_errors);
}
}
// try to extract the first packet to send on the new route (=> packet destined to the reply source)
data_pk_ptr=dsr_extract_buffer(route_destination_dsr_address);
// if a packet was found in the buffer
if (data_pk_ptr!=OPC_NIL)
{
dsr_transmit_data(data_pk_ptr,route_destination_dsr_address,1);
}
// destroy the reply packet
op_pk_destroy(pk_ptr);
}
// if the node is the relay of the reply packet
else if (my_dsr_address==intended_relay_dsr_address)
{
// if the promiscuous reply mode is activated
dsr_promiscuous_reply(pk_ptr);
/* forward reply */
dsr_forward_reply(pk_ptr);
}
// if we are not concerned by the reply packet
else if (sequence_number!=-1)
{
// if the promiscuous reply mode is activated
dsr_promiscuous_reply(pk_ptr);
// destroy the reply packet
i=0;
current_node_index=-1;
// check if the current node is in the reply path
do
{
sprintf(field,"Node_%d",i);
op_pk_nfd_get(pk_ptr,field,&node_dsr_address);
if (node_dsr_address==my_dsr_address)
{
current_node_index=i;
}
else
{
i++;
}
}
while ((current_node_index==-1)&&(i<seg_left));
// if the node is in the path then there is a shorter path than the one used by the reply packet
if (current_node_index!=-1)
{
// "calculate" and set the reply packet route with this shorter path
for (i=0;i<size_route-(seg_left+1);i++)
{
sprintf(field,"Node_%d",i+seg_left);
op_pk_nfd_get(pk_ptr,field,&node_dsr_address);
sprintf(field,"Node_%d",i+current_node_index+1);
op_pk_nfd_set(pk_ptr,field,node_dsr_address);
}
// and update the Size_Route and Seg_left of the reply packet
op_pk_nfd_set(pk_ptr,"Opt_Data_Len",size_route-(seg_left-current_node_index));
op_pk_nfd_set(pk_ptr,"IP_TTL",current_node_index+1);
dsr_message("I have just found a shorter path for the reply\n");
dsr_forward_reply(pk_ptr);
}
else
{
dsr_message("I am not concerned by the reply thus I am destroying it\n");
op_pk_destroy(pk_ptr);
}
}
}
// if the reply has already been received by the node
else
{
dsr_promiscuous_reply(pk_ptr);
// it is destroyed
op_pk_destroy(pk_ptr);
}
// breakpoints for debugging purpose
if (1)
{
op_prg_odb_bkpt("handle_reply");
}
if (sequence_number==-1)
{
op_prg_odb_bkpt("handle_gratuitous_reply");
}
}
/*************************************************************/
/* DSR_REPLY_ALREADY_SEEN */
/*************************************************************/
/* This function checks if the reply identified by its source,
/* its destination and its sequence_number has been already
/* seen and consequently handled
/*
/* int source_dsr_address: the dsr address of the reply source
/* int
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -