📄 aodv_routing.pr.c
字号:
op_ici_install(ici_ptr);// send packet to mac layerop_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(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 subqueueop_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++; 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 emptyif (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--; 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 entryif(DEBUG > 1 ) printf(" > Check routing table for entry\n");
// print entry if any availableif(DEBUG >1) aodv_entry_print(destination);// get packet from sub-queueif(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 attributesackEvt= (AckEvt*) op_prg_mem_alloc(sizeof(AckEvt));
if (ackEvt!=NULL)
{ // Schedule interruption with the appropriate code (destination to which packet has been sent)
ackEvt->evt=op_intrpt_schedule_remote(op_sim_time()+ Wait_ACK,destination,op_id_self()); // store a copy of the sent packet ackEvt->copy_pk_ptr = op_pk_copy(pk);
// Store the Ack evt in the AckEvt list putInFifoMultiplex(&ackEvtFifo,ackEvt,destination); }
}
/////////////////////////////////////////////////////////////////
/*********************** Generate RREQ *************************//////////////////////////////////////////////////////////////////
void aodv_rreq_pk_generate(int destination, Request_Status_Type status)
{
Packet* rreq_pk_ptr;/*/* Initiate the discovery process by generating a RREQ for a given/* destination./* The procedure not only generates a RREQ packet with the appropiate/* fields. But it also updates node's "RequestSent" repository (see /* function aodv_requestSent_repository_update).*/if(DEBUG > 1) printf(" - Function aodv_rreq_pk_generate(destination %d)\n", destination);
// check if no request is already pending for that destinationif(RequestSent[destination].status == OFF) { // Create a request type packet
rreq_pk_ptr = op_pk_create_fmt("AODV_RREQ");
// set RREQ fields op_pk_nfd_set(rreq_pk_ptr,"TTL",RequestSent[destination].ttl);
op_pk_nfd_set(rreq_pk_ptr,"G",RequestSent[destination].gratuitous); op_pk_nfd_set(rreq_pk_ptr,"SRC",node_addr);
op_pk_nfd_set(rreq_pk_ptr,"DEST",destination);
op_pk_nfd_set(rreq_pk_ptr,"DestSeqNb",aodv_entry_destSeqNb_get(destination));
op_pk_nfd_set(rreq_pk_ptr,"SrcSeqNb",mySeqNb);
op_pk_nfd_set(rreq_pk_ptr,"BroadcastID",myBroadcastID); //increment node's boadcastID myBroadcastID++;
// send to mac layer if(DEBUG > 1 ) printf(" > RREQ packet has been generated\n");
aodv_pk_send_to_mac_layer(rreq_pk_ptr, BROADCAST); // update RequestSent repository aodv_requestSent_repository_update(destination, status); }else { if(DEBUG > 1 ) printf(" > A request is pending: cannot renew it\n");
}if(DEBUG > 1 ) printf(" - Function aodv_rreq_pk_generate() done\n");
}//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//// void aodv_requestSent_repository_update(int dest ) ////~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//void aodv_requestSent_repository_update(int destination, Request_Status_Type status) { /* /* When a request is sent, a corresponding entry is /* updated in the RequestSent repository in order /* to control route requests broadcast. For each request /* that has been generated, node stores the destination /* sequence number, the number of retries, the status /* of the request, the expiration time (time before /* renewal), and finally the future TTL to use in case /* of renewal */ // Store the dest seq nb of the request RequestSent[destination].sequence_number=aodv_entry_destSeqNb_get(destination);
// Set the status of the request RequestSent[destination].status= status;
// schedule for interruption if no reply received within appropriate period RequestSent[destination].evt = op_intrpt_schedule_remote(op_sim_time()+2*RequestSent[destination].ttl*NODE_TRAVERSAL_TIME,NREPLY_CODE+destination,op_id_self()); RequestSent[destination].expirationTime= op_sim_time()+ 2*RequestSent[destination].ttl* NODE_TRAVERSAL_TIME; // increment TTL for next eventual renewal RequestSent[destination].ttl=RequestSent[destination].ttl+TTL_INCREMENT; if(RequestSent[destination].ttl > TTL_TRESHOLD) { RequestSent[destination].ttl= NET_DIAMETER; // Increment the number of retries
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -