📄 aodv_routing_add.pr.c
字号:
#define global_control_pk_cnt_stathandle pr_state_ptr->global_control_pk_cnt_stathandle
#define global_data_pk_cnt_stathandle pr_state_ptr->global_data_pk_cnt_stathandle
#define pk_error_count pr_state_ptr->pk_error_count
#define pk_error_cnt_stathandle pr_state_ptr->pk_error_cnt_stathandle
#define global_error_pk_cnt_stathandle pr_state_ptr->global_error_pk_cnt_stathandle
#define global_nerror_pk_cnt_stathandle pr_state_ptr->global_nerror_pk_cnt_stathandle
#define global_repair_pk_cnt_stathandle pr_state_ptr->global_repair_pk_cnt_stathandle
#define global_receive_data_pk_cnt_stathandle pr_state_ptr->global_receive_data_pk_cnt_stathandle
#define global_buffer_size_stathandle pr_state_ptr->global_buffer_size_stathandle
/* This macro definition will define a local variable called */
/* "op_sv_ptr" in each function containing a FIN statement. */
/* This variable points to the state variable data structure, */
/* and can be used from a C debugger to display their values. */
#undef FIN_PREAMBLE
#define FIN_PREAMBLE aodv_routing_add_state *op_sv_ptr = pr_state_ptr;
/* Function Block */
enum { _block_origin = __LINE__ };
/////////////////////////////////////////////////////////////////
/**************** aodv_pk_send_to_mac_layer () ****************/
/////////////////////////////////////////////////////////////////
void
aodv_pk_send_to_mac_layer(Packet *pk, int nextHop)
{
Ici* ici_ptr;
int pk_type,src;
/*
/* Send packet (pk) to the MAC layer interface. The routine also
/* installs an ICI in order to indicate the next hop address to
/* which the packet should be sent.
*/
op_pk_nfd_get(pk,"Type",&pk_type);
if(pk_type == DATA_PACKET_TYPE)
{
pk_data_count = pk_data_count + 1;
op_stat_write(pk_data_cnt_stathandle, pk_data_count);
op_stat_write(global_data_pk_cnt_stathandle, ++global_data_pk_cnt);
}
else
{
pk_control_count = pk_control_count + 1;
op_stat_write(pk_control_cnt_stathandle, pk_control_count);
op_stat_write(global_control_pk_cnt_stathandle, ++global_control_pk_cnt);
}
if(pk_type == ERROR_PACKET_TYPE)
{
//pk_error_count = pk_error_count + 1;
//op_stat_write(pk_error_cnt_stathandle, pk_error_count);
op_stat_write(global_error_pk_cnt_stathandle, ++global_error_pk_cnt);
}
else
{
//op_stat_write(global_nerror_pk_cnt_stathandle, ++global_nerror_pk_cnt);
}
// set IP header
// PreviousHop field = source IP address
op_pk_nfd_set(pk,"PreviousHop",node_addr);
// NextHop field = destination IP address
op_pk_nfd_set(pk,"NextHop",nextHop);
// set TR_source field for Transmission Range purpouse
op_pk_nfd_set(pk,"TR_source",node_id);
// print packet
if(DEBUG > 1) aodv_pk_print(pk);
// create and install an ici to communicate the packet destination
// to the MAC layer interface.
ici_ptr = op_ici_create("aodv_notice_to_send");
op_ici_attr_set(ici_ptr,"Packet_Destination",nextHop);
op_ici_install(ici_ptr);
// send packet to mac layer
op_pk_send(pk,SEND_STRM);
if (DEBUG > 1) printf(" > Packet succesfully sent to MAC layer\n ");
}
/////////////////////////////////////////////////////////////////
/***************** aodv_data_pk_route() *********************/
/////////////////////////////////////////////////////////////////
void
aodv_data_pk_route(Packet* data_pk_ptr)
{
RoutingTableEntry * entryPtr;
int dest, g_flag, nextHop;
/*
/* Receive the upcoming data packet stream from the
/* upper layer and route it to its destination.
/* Two scenarios are possible:
/* 1. Another packet destined for the same node
/* is waiting in the sub-queue. The procedure then
/* only enqueues the data packet in the sub-queue
/* and waits for the next call.
/* 2. Sub-queue is empty. The procedure checks its
/* routing table in order to find out the next hop
/* toward the destination.
/* 2.a. If no entry was found, the procedure
/* enqueues the packet in the corresponding sub-
/* queue. Then, the procedure checks whether a RREQ
/* has been generated for this destination or not.
/* If not, the procedure calls the appropriate function
/* to generate a RREQ. Else, it waits for the next call.
/* 2.b. If an entry exists, the procedure send the
/* packet to the MAC layer with the appropriate next
/* hop destination address.
*/
// read packet
op_pk_nfd_get(data_pk_ptr,"DEST",&dest);
op_pk_nfd_get(data_pk_ptr,"G",&g_flag);
if(DEBUG > 1) printf(" - Function aodv_data_pk_route(destination %d)\n", dest);
if(aodv_buffer_is_empty(dest) == OPC_FALSE)
{
// enqueue data packet into appropriate buffer
if(DEBUG > 1) printf(" > Buffer not empty: enqueue packet into buffer\n");
aodv_data_pk_queue(data_pk_ptr);
}
else
{
// check routing table for entry
if(DEBUG > 1) printf(" > Check routing table for entry\n");
entryPtr = aodv_routingTable_entry_get(dest);
// print entry if any
if(DEBUG > 1) aodv_entry_print(dest);
// get next hop along the path if any
nextHop = aodv_entry_nextHop_get(dest);
if ((nextHop != NOT_VALID) && (nextHop != NON_EXISTENT))
{
//node has an active entry for dest
if(DEBUG > 1) printf(" > Node has active fresh enough entry: packet is sent [next hop is %d]\n", nextHop);
// schedule an event if no ack received within the waiting window
if(DEBUG > 3) printf(" > Schedule ack-timeout event\n");
aodv_ack_timeout_schedule(data_pk_ptr,dest);
// send packet to mac layer
aodv_pk_send_to_mac_layer(data_pk_ptr,nextHop);
// refresh entry timeout
if(DEBUG > 1 ) printf(" > Refresh expiration time for entry\n");
aodv_entry_expirationTime_set(dest,op_sim_time()+ACTIVE_ROUTE_TIMEOUT);
}
else
{
if(DEBUG > 1 ) printf(" > No entry available: Data packet is inserted into buffer.\n");
// insert packet into buffer
aodv_data_pk_queue(data_pk_ptr);
// check
whether node should generate a request or not
if(RequestSent[dest].status==OFF)
{
// No request pending for this destination
// generate route request for desination
if(DEBUG > 1 ) printf(" > No request pending: Generate RREQ packet\n");
RequestSent[dest].gratuitous = g_flag;
if(nextHop == NOT_VALID) // Entry invalid: Set TTL to last known Hop Count
RequestSent[dest].ttl = max_int(entryPtr->lastHopCount,TTL_START);
// Generate rreq
aodv_rreq_pk_generate(dest, WAITING_FOR_REPLY);
}
else
{
// request is either under repair or waiting for a reply
if(DEBUG > 1 ) printf(" > A request has already been sent: node waiting for reply\n");
}
}
}
if(DEBUG > 1 ) printf(" - Function aodv_data_pk_route() done\n");
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
// void aodv_data_pk_queue(Packet* pack) //
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
void
aodv_data_pk_queue(Packet* pk)
{
int destination;
/*
/* Queue data packet in the corresponding sub-queue.
*/
// Read the DEST field (packet's final destination) in order to have index of subqueue
op_pk_nfd_get(pk,"DEST",&destination);
// Enqueue packet in the correct subqueue
if (op_subq_pk_insert(destination,pk,OPC_QPOS_TAIL) != OPC_QINS_OK)
{
if(DEBUG > 3) printf(" > Fail to insert packet in subqueue \n");
op_pk_destroy(pk);
}
else
{
if(DEBUG > 1 ) printf(" > %d data packets waiting for destination %d\n", aodv_buffer_size_get(destination),destination);
data_pk_buffer++;
op_stat_write(global_buffer_size_stathandle, data_pk_buffer);
stats[node_addr].data_pk_buffer++;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
// Boolean aodv_buffer_is_empty(int destination) //
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
Boolean
aodv_buffer_is_empty(int destination)
{
/*
/* Check whether the given sub-queue (the one whose
/* index equals to destination) is empty or not.
/* Return OPC_TRUE if buffer is empty. OPC_FALSE otherwise.
*/
return op_subq_empty(destination);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
// int aodv_buffer_size_get(int destination)
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
int
aodv_buffer_size_get(int destination)
{
/*
/* Return the number of data packets waiting
/* for this destination.
*/
return op_subq_stat(destination, OPC_QSTAT_PKSIZE);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
// Packet* aodv_data_pk_dequeue(int destination) //
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
Packet*
aodv_data_pk_dequeue(int destination)
{
Packet* data_pk_ptr;
/*
/* Return the first packet (first in) from
/* the indicated data buffer.
*/
// If buffer not empty
if (aodv_buffer_is_empty(destination) == OPC_FALSE)
{
// get data packet from queue
data_pk_ptr = op_subq_pk_remove(destination,OPC_QPOS_HEAD);
// Decrement the number of data packets waiting into the buffer
data_pk_buffer--;
op_stat_write(global_buffer_size_stathandle, data_pk_buffer);
stats[node_addr].data_pk_buffer--;
}
else
if(DEBUG > 3) printf(" > Buffer empty \n");
return data_pk_ptr;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
// void aodv_buffer_serve(int dest) //
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
void
aodv_buffer_serve(int destination)
{
Packet* data_pk_ptr;
int nextHop = aodv_entry_nextHop_get(destination);
/*
/* This routine is called when a new entry is available for
/* a given destination. When called, the procedure dequeues the first packet
/* waiting in the corresponding buffer, reads the next hop destination
/* from the routing table, then sends the data packet to the MAC layer
/* with the appropriate destination IP address.
*/
if(DEBUG > 1 ) printf(" - Function aodv_buffer_serve(destination %d)\n",destination);
if(! aodv_buffer_is_empty(destination))
{
// Check routing table for entry
if(DEBUG > 1 ) printf(" > Check routing table for entry\n");
// print entry if any available
if(DEBUG >1) aodv_entry_print(destination);
// get packet from sub-queue
if(DEBUG > 1 ) printf(" > Get packet from buffer\n");
data_pk_ptr = aodv_data_pk_dequeue(destination);
if((nextHop != NOT_VALID) && (nextHop != NON_EXISTENT))
{
if(DEBUG > 1 ) printf(" > Node has a fresh active entry\n");
// schedule an event if no ack received within the waiting window
if(DEBUG > 3 ) printf(" > Arming Ack Timer\n");
aodv_ack_timeout_schedule(data_pk_ptr,destination);
// send packet to mac layer
aodv_pk_send_to_mac_layer(data_pk_ptr,nextHop);
// refresh entry timeout
if(DEBUG > 2 ) printf(" > Refresh expiration time for entry:\n");
aodv_entry_expirationTime_set(destination,op_sim_time()+ACTIVE_ROUTE_TIMEOUT);
}
else
{
if(DEBUG > 1 ) printf(" > Error @ aodv_buffer_serve():: no valid entry was found !\n");
// call route function
aodv_data_pk_route(data_pk_ptr);
}
}
else
{
if(DEBUG > 1 ) printf(" > Error @ aodv_buffer_serve():: buffer empty !\n");
}
if(DEBUG > 1 ) printf(" - Function aodv_buffer_serve() done\n");
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
// void aodv_ack_timeout_schedule(Packet* pk, int destination) //
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
void
aodv_ack_timeout_schedule(Packet* pk, int destination)
{
AckEvt* ackEvt;
/*
/* This routine is called when a data packet is sent to the
/* MAC Layer. As a matter of fact, this procedure schedules
/* an interruption in Wait_Ack seconds of the current time.
/* If no ack is received within this period of time, the
/* process transits to the Ack_Timeout State in order to re-
/* transmit the lost packet.
/* However, if an ack is received, the ack-timeout interruption
/* is cancelled (see Rcv_Ack State).
*/
if(DEBUG > 3 ) printf(" - Function aodv_ack_timeout_schedule(destination %d)\n", destination);
// create an AckEvt structure to store interruption attributes
ackEvt= (AckEvt*) op_prg_mem_alloc(sizeof(AckEvt));
if (ackEvt!=NULL)
{
// Schedule interruption with the appropriate code (destination to which packet has been sent)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -