📄 aodv_routing_add.pr.c
字号:
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 destination
if(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));
mySeqNb++;
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
RequestSent[destination].nbOfRetries++;
}
}
/////////////////////////////////////////////////////////////////
/*********************** HANDLE REQUEST ************************/
/////////////////////////////////////////////////////////////////
void
aodv_rreq_pk_receive(Packet* rreq_pk_ptr)
{
int dest,
destSeqNb,
source,G;
/*
/* Process the received RREQ. This procedure decides
/* whether node should generate a RREP packet for the
/* requested destination or simply forward it to the
/* neighbouring nodes.
/* Note that RREQ is automatically discarded if seen
/* less than BROADCAST_RECORD_TIME seconds ago
*/
if(DEBUG > 1) printf(" - Function aodv_rreq_pk_receive()\n");
// reading packet
op_pk_nfd_get (rreq_pk_ptr,"DEST",&dest);
op_pk_nfd_get (rreq_pk_ptr,"SRC",&source);
op_pk_nfd_get (rreq_pk_ptr,"DestSeqNb",&destSeqNb);
op_pk_nfd_get (rreq_pk_ptr,"G",&G);
// check if RREQ has already been seen
if(aodv_rreq_pk_is_fresh_enough(rreq_pk_ptr) == OPC_TRUE)
{
//request NEVER seen OR SEEN more than BROADCAST_RECORD_TIME ago
if(DEBUG > 1 ) printf(" > RREQ is fresh enough: request handled \n");
// update or create reverse entry
aodv_entry_update_or_create_from_rreq(rreq_pk_ptr);
// handle request
if(node_addr == dest) // the current node is the destination
{
if(DEBUG > 1 ) printf(" > RREQ has reached its destination: node replies\n");
aodv_rrep_pk_generate_from_destination(rreq_pk_ptr);
}
else // the node is an intermediate node
{
if(DEBUG > 1 ) printf(" > Node is a relay\n");
if(aodv_fresh_enough_entry_is_available(dest,destSeqNb)== OPC_TRUE)
{
if(DEBUG > 1) aodv_entry_print(dest);
// node has a fresh enough route
if(DEBUG > 1 ) printf(" > Node has active fresh enough entry: node replies\n");
// if gratuitous mode requested, generate gratuitous RREP for destination
if(G)
{
if(DEBUG > 1 ) printf(" > Gratuitous reply requested: generate reply for destination\n");
aodv_gratuitous_rrep_pk_generate(rreq_pk_ptr);
}
// generate rrep for source
if(DEBUG > 1 ) printf(" > Generate reply for the source node\n");
aodv_rrep_pk_generate_from_relay(rreq_pk_ptr);
}
else // node doesn't have any active entry for the requested
route
{
if(DEBUG > 1 ) printf(" > No active entry for requested route: RREQ should be forwarded\n");
aodv_rreq_pk_forward(rreq_pk_ptr);
}
}
// print reverse entry if any
if(DEBUG > 1) printf(" > Print reverse entry if any available\n");
if(DEBUG > 1) aodv_entry_print(source);
// print forward entry if any
if(DEBUG > 1) printf(" > Print forward entry if any available\n");
if(DEBUG > 1) aodv_entry_print(dest);
}
else //request seen less than BROADCAST_RECORD_TIME ago
{
// RREQ discarded
if(DEBUG > 1 ) printf(" > Request seen less than BRODCAST_RECORD_TIME ago: RREQ discarded\n");
op_pk_destroy(rreq_pk_ptr);
}
if(DEBUG > 1 ) printf(" - Function aodv_rreq_pk_receive() done\n");
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
// void aodv_rrep_pk_generate_from_destination(Packet* rreq_pk_ptr) //
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
void
aodv_rrep_pk_generate_from_destination(Packet* rreq_pk_ptr)
{
Packet* rrep_pk_ptr;
int previousHop,
source,
dest,
destSeqNb;
/*
/* This function is called when a RREQ has reached its
/* destination and node wants to reply.
/* Once the RREQ packet is generated, the procedure unicat
/* it back to the node upstream (node from which RREQ was
/* received) (PreviousHop field).
*/
// Read the received RREQ packet
op_pk_nfd_get (rreq_pk_ptr,"SRC",&source);
op_pk_nfd_get (rreq_pk_ptr,"DEST",&dest);
op_pk_nfd_get (rreq_pk_ptr,"PreviousHop",&previousHop);
op_pk_nfd_get (rreq_pk_ptr,"DestSeqNb",&destSeqNb);
// Create reply packet
rrep_pk_ptr = op_pk_create_fmt("AODV_RREP");
// Assign source and dest to the reply packet
op_pk_nfd_set(rrep_pk_ptr,"SRC",source);
op_pk_nfd_set(rrep_pk_ptr,"DEST",dest);
op_pk_nfd_set(rrep_pk_ptr,"HopCount",0);
op_pk_nfd_set(rrep_pk_ptr,"Lifetime",MY_ROUTE_TIMEOUT);
// Assign seq number
mySeqNb = max_int(destSeqNb, mySeqNb);
op_pk_nfd_set(rrep_pk_ptr,"DestSeqNb",mySeqNb);
if(DEBUG > 1 ) printf(" > RREP has been generated from destination: unicast it to source node [next hop is %d]\n", previousHop);
// send reply packet
aodv_pk_send_to_mac_layer(rrep_pk_ptr,previousHop);
// Refresh timeout
aodv_entry_expirationTime_set(source,op_sim_time()+ACTIVE_ROUTE_TIMEOUT);
// Destroy rreq
op_pk_destroy(rreq_pk_ptr);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
// void aodv_gratuitous_rrep_pk_generate(rreq_pk_ptr) //
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
void
aodv_gratuitous_rrep_pk_generate(rreq_pk_ptr)
{
Packet* grat_rrep_pk_ptr;
RoutingTableEntry * forwardEntryPtr;
int dest,
source,
srcSeqNb,
hopCount;
double lifetime;
/*
/* Generate a gratuitous RREP and unicast it to
/* the destination node (node for which RREQ was
/* originally generated).
*/
// Read RREQ packet
op_pk_nfd_get (rreq_pk_ptr,"SRC",&source);
op_pk_nfd_get (rreq_pk_ptr,"DEST",&dest);
op_pk_nfd_get (rreq_pk_ptr,"SrcSeqNb",&srcSeqNb);
op_pk_nfd_get (rreq_pk_ptr,"HopCount",&hopCount);
// read forward entry
forwardEntryPtr = aodv_routingTable_entry_get(dest);
// create a gratuitous rrep packet and unicast it to the next hop toward the Destination
grat_rrep_pk_ptr= op_pk_create_fmt("AODV_RREP");
op_pk_nfd_set(grat_rrep_pk_ptr,"SRC",dest);
op_pk_nfd_set(grat_rrep_pk_ptr,"DEST",source);
op_pk_nfd_set(grat_rrep_pk_ptr,"DestSeqNb",srcSeqNb);
op_pk_nfd_set(grat_rrep_pk_ptr,"HopCount",hopCount+1);
lifetime = forwardEntryPtr->expirationTime - op_sim_time();
if(lifetime <= 0)
lifetime = ACTIVE_ROUTE_TIMEOUT;
op_pk_nfd_set(grat_rrep_pk_ptr,"Lifetime",lifetime);
// send to MAC Layer
aodv_pk_send_to_mac_layer(grat_rrep_pk_ptr,aodv_entry_nextHop_get(dest));
// Refresh timeout
aodv_entry_expirationTime_set(dest,op_sim_time()+ACTIVE_ROUTE_TIMEOUT);
if (DEBUG > 1) printf(" > Gratuitous RREP has been generated: unicast it to destination [next hop is %d]\n", aodv_entry_nextHop_get(dest));
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
// void aodv_rrep_pk_generate_from_relay(Packet* ) //
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
void
aodv_rrep_pk_generate_from_relay(Packet* rreq_pk_ptr)
{
Packet *rrep_pk_ptr;
double lifetime;
RoutingTableEntry *forwardEntryPtr;
RoutingTableEntry *reverseEntryPtr;
int dest;
int source;
int previousHop;
/*
/* This routine is called when an intermediate node
/* receives a RREQ an has fresh enough route to
/* to generate a RREP for the requested destination.
*/
// Read request packet
op_pk_nfd_get (rreq_pk_ptr,"SRC",&source);
op_pk_nfd_get (rreq_pk_ptr,"DEST",&dest);
op_pk_nfd_get (rreq_pk_ptr,"PreviousHop",&previousHop);
// Read forward entry
forwardEntryPtr=aodv_routingTable_entry_get(dest);
// Create reply packet
rrep_pk_ptr = op_pk_create_fmt("AODV_RREP");
/* Assign source and dest to the reply packet */
op_pk_nfd_set(rrep_pk_ptr,"SRC",source);
op_pk_nfd_set(rrep_pk_ptr,"DEST",dest);
op_pk_nfd_set(rrep_pk_ptr,"HopCount",forwardEntryPtr->hopCount);
lifetime = forwardEntryPtr->expirationTime - op_sim_time();
if(lifetime <= 0)
lifetime = ACTIVE_ROUTE_TIMEOUT;
op_pk_nfd_set(rrep_pk_ptr,"Lifetime",lifetime);
op_pk_nfd_set(rrep_pk_ptr,"DestSeqNb",forwardEntryPtr->destSeqNb);
// add previousHop toward "source" to the precursor list of the forward entry
aodv_listOfPrecursors_node_put(forwardEntryPtr,previousHop);
// add nextHop toward "destination" to the precursor list of the reverse entry
reverseEntryPtr=aodv_routingTable_entry_get(source);
aodv_listOfPrecursors_node_put(reverseEntryPtr,forwardEntryPtr->nextHop);
// send reply to mac layer
if(DEBUG > 1 ) printf(" > RREP has been generated from relay: unicast it to source node [next hop is %d]\n",previousHop);
aodv_pk_send_to_mac_layer(rrep_pk_ptr,previousHop);
// Refresh timeout
aodv_entry_expirationTime_set(source,op_sim_time()+ACTIVE_ROUTE_TIMEOUT);
// Destroy rreq
op_pk_destroy(rreq_pk_ptr);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
// void aodv_rreq_pk_forward(Packet* rreq_pk_ptr) //
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
void
aodv_rreq_pk_forward(Packet* rreq_pk_ptr)
{
int ttl,
hopCount;
/*
/* Node does not have a fresh enough entry
/* (or does not have an entry at all) to answer
/* the received RREQ, so it decides to forward
/* it. Node increments the Hop Count field
/* and decrements the TTL field.
/* Note that packet is sent to mac layer only if
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -