⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 aodv_routing.pr.c

📁 在OPNET中实现AODV路由协议
💻 C
📖 第 1 页 / 共 5 页
字号:
			reverseEntryPtr->nextHop= previousHop;
			if(reverseEntryPtr->hopCount != INFINITY)

				reverseEntryPtr->lastHopCount= reverseEntryPtr->hopCount;

			reverseEntryPtr->hopCount=hopCount+1;

			}
		else
			if(DEBUG > 1) printf("      > Node does not need to update its reverse entry\n");

		
		// Refresh entry timeout to max(current expiration time, currentTime+REV_ROUTE_LIFE)	
		if((op_sim_time()+REV_ROUTE_LIFE) > reverseEntryPtr->expirationTime)			
			{			
			aodv_entry_expirationTime_set(source,op_sim_time()+REV_ROUTE_LIFE);
			}
		else
			if(DEBUG > 1) printf("      > Reverse entry timeout does not need to be refreshened\n");


		// set entry status
		reverseEntryPtr->status = ACTIVE;
		}
	else  

		{
		//entry doesn't exist: node creates it
		if(DEBUG > 1 ) printf("      > Node creates a reverse entry to source node\n");

		reverseEntryPtr=aodv_entry_create_new();
		reverseEntryPtr->listOfPrecursors=newFifo();

		reverseEntryPtr->status = ACTIVE;
		reverseEntryPtr->dest=source;

		reverseEntryPtr->destSeqNb=srcSeqNb;

		reverseEntryPtr->nextHop= previousHop;

		reverseEntryPtr->hopCount=hopCount+1;
		reverseEntryPtr->lastHopCount = hopCount+1;
		// Add the entry to the RoutingTable
		aodv_routingTable_entryPtr_put(reverseEntryPtr);

		// Refresh entry timeout
		aodv_entry_expirationTime_set(source,op_sim_time()+REV_ROUTE_LIFE);
		}
	
	// if reverse entry updated or created, then
	// Serve buffer if any packet's waiting
	if(reverseEntryPtr->hopCount != INFINITY)
		aodv_buffer_serve(source);
	}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
// void aodv_rreq_pk_regenerate(int destination)            //
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//

void 
aodv_rreq_pk_regenerate(int destination)

{


/*
/* This function is called in the Renew_Request state when 
/* the previous RREQ didn't receive any RREP and the number
/* of retries is smaller than TTL_RETRIES_TRESHOLD
*/

aodv_rreq_pk_generate(destination, WAITING_FOR_REPLY);

}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
// void aodv_reverseListOfPrecursors_update(int prec, int dest)       //
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//

void 
aodv_reverseListOfPrecursors_update(int precursor, int destination)

	{


	int      *destinationPtr; 

	sFifo    *listOfDestination;


	/*
	/* Each time a node "A" (precursor) is added to the list of precursor of 
	/* a given destination "B" (detination), this function is called to add
	/* "B" in the list of nodes to which "A" is a precursor. Thus, when 
	/* link to A is no longer available and node wants to expunge it from 
	/* its routing table, node has only to process entry that are listed
	/* within the reverseListOfPrecursol at the entry "A".
	*/
	
	// var init
	destinationPtr = (int*) op_prg_mem_alloc(sizeof(int));

	*destinationPtr = destination;

	// begin

	if(DEBUG > 3 ) printf("      - Function aodv_reverseListOfPrecursors_update(): precursor = %d || entry = %d\n", precursor,destination);

	// check if a reverse entry already exists for PRECURSOR

	if(DEBUG > 3 ) printf("      > check if a reverse entry already exists\n");

	listOfDestination= (sFifo*) readInFifoMultiplex(reverseListOfPrecursors, precursor);

	

	if(listOfDestination == OPC_NIL) // no entry available

		{

		if(DEBUG > 3 ) printf("      > No entry available: node has to create a new one\n");

		// have to create a new entry

		listOfDestination=newFifo();

		putInFifo(listOfDestination, destinationPtr);

		putInFifoMultiplex(reverseListOfPrecursors,listOfDestination, precursor);

		}

	else

		{

		// only add destination to the list of destination

		if(DEBUG > 3 ) printf("      > entry already exists: only add destination to the list of destination\n");

		putInFifo(listOfDestination, destinationPtr);

		}

	if(DEBUG > 3 ) printf("      - function aodv_reverseListOfPrecursors_update()... done !\n");

   }


///////////////////////////////////////////////////////////

/***************** HANDLE_DATA ***************************/

///////////////////////////////////////////////////////////



void 
aodv_data_pk_receive(Packet* data_pk_ptr)

{

// var

int        previousHop, source, dest; 

/*
/* This function receives the upcoming data packet from the MAC Layer.
/* Two possibilities:
/* 1. Packet has reached its destination. Packet is then discarded toward
/*    the upper_layer.
/* 2. Packet has to be forwarded. Node checks its routing table and
/*    either forwards the packet if an entry is available or generates
/*    a RERR otherwise.
/* 
*/

// Read data packet 
op_pk_nfd_get (data_pk_ptr,"PreviousHop",&previousHop);


op_pk_nfd_get (data_pk_ptr,"SRC",&source);

op_pk_nfd_get (data_pk_ptr,"DEST",&dest); 



if(DEBUG > 1 ) printf("    - Function aodv_data_pk_receive(destination is %d )\n",dest);

// update stats
if(previousHop != source)
	{
	stats[previousHop].forward_output++;
	}

// check packet final destination
if (dest == node_addr)  

	{
	// pk has reached its destination
	if(DEBUG > 1 ) printf("      > Data packet has reached its destination\n");
	// send packet to upper layer 
	if(DEBUG > 1 ) printf("      > Data packet sent to app_manager layer\n");
	op_pk_send(data_pk_ptr,DISCARD_STRM); 

	// update stats
	output ++;
	stats[source].own_output++;
	}

else  

	{
	// pk has to be forwarded
	if(DEBUG > 1 ) printf("      > Node is a relay: packet has to be routed\n");
	// update forward input stat
	stats[node_addr].forward_input++;

	// check routing table for desired entry 
	if(DEBUG > 1) printf("      > Check routing table for entry\n");
	if(DEBUG > 1) aodv_entry_print(dest);
	if ((aodv_entry_nextHop_get(dest) != NOT_VALID) && (aodv_entry_nextHop_get(dest) != NON_EXISTENT))
		 {

		 // entry available: node forwards the packet 

		 if(DEBUG > 1 ) printf("      > Node has fresh enough active entry\n      > Data packet forwarded\n");
		 // schedule an event if no ack received within the waiting window 
		 if(DEBUG > 3) printf("      > Schedule Event if no ack received\n");

		 aodv_ack_timeout_schedule(data_pk_ptr,dest);

		 //send to mac

		 aodv_pk_send_to_mac_layer(data_pk_ptr,aodv_entry_nextHop_get(dest));

		 // re-active the route timeout (must delay the expiration event 

		 // which has been scheduled for the current entry)
		 aodv_entry_expirationTime_set(dest,op_sim_time()+ACTIVE_ROUTE_TIMEOUT); 
		 }

	 else if(aodv_entry_nextHop_get(dest) == NOT_VALID)
		 {

		 printf("      > Error @ node %d: No forward route available: no active entry for dest %d\n",node_addr,dest);
		 // insert data packet into buffer and try to repair the broken link
		 if(DEBUG > 1 ) printf("      > Insert packet into buffer\n");
		 aodv_data_pk_queue(data_pk_ptr);
		 // if no repair pending
		 if(RequestSent[dest].status != WAITING_FOR_REPAIR)
			 {
			 // cancel expiration time
			 aodv_entryPtr_expirationInterrupt_cancel(aodv_routingTable_entry_get(dest));
			 // attempt to repair
			 if(DEBUG > 1 ) printf("      > Attempt to repair link\n");
			 aodv_link_repair_attempt(dest, aodv_entry_hopCount_get(source));
			 }
		 }
	 else // entry does not exist
		 {
		 // generate a rreq
		 aodv_rreq_pk_generate(dest, WAITING_FOR_REPLY);
		 }

	 }

	if(DEBUG > 1 ) printf("    - Function aodv_data_pk_receive() done\n");

}






/***********************************************************/

/***************** INIT ROUTING TABLE ENTRY ****************/

/***********************************************************/


RoutingTableEntry* 
aodv_entry_create_new()

{


RoutingTableEntry* entryPtr;


/*
/* Returns a new routing table entry with the default
/* values.
*/

entryPtr= (RoutingTableEntry*) op_prg_mem_alloc(sizeof(RoutingTableEntry));

entryPtr->status             = ACTIVE;

entryPtr->dest               = -1;
entryPtr->nextHop            = -1;

entryPtr->destSeqNb          =  0; 
entryPtr->hopCount           = -1;
entryPtr->lastHopCount       = -1;
entryPtr->expirationTime     =  0;
entryPtr->lastExpirationTime =  0;

return entryPtr;

}



/////////////////////////////////////////////////////////////////

/*********************** GENERATE ERROR ************************/

/////////////////////////////////////////////////////////////////

void 
aodv_rerr_pk_generate(int unreachableNode, int n_flag)

{

// vars

RoutingTableEntry *  indexEntryError;
ErrorContentStruct*  newErrorStructPtr;
 
sObject*             object;

Packet*              rerr_pk_ptr;
int                  source,
                     dest,
					 destSeqNb,
					 unreachableDest,
					 unreachableDestSeqNb,
					 i;

/*
/* Generate a RERR packet containing the list of all
/* destinations (and their associated Dest. Seq. Nb.)
/* that are now unreachable because of the loss of 
/* node given in the first parameter (unreachableNode). 
/* The N flag (n_flag) indicates whether entry should 
/* be deleted or not.
*/

//init vars
object=  routingTable->firstObject;
newErrorStructPtr= (ErrorContentStruct *) 

		 				op_prg_mem_alloc(sizeof(ErrorContentStruct));

newErrorStructPtr->listOfUnreachableDest=newFifo();


// Begin
if(DEBUG > 1) printf("    - Function aodv_rerr_pk_generate(destination %d)\n", unreachableNode);

// Read corresponding entry
indexEntryError = aodv_routingTable_entry_get(unreachableNode);
// check the non_delete flag
if(n_flag == 0)
	{
	// If not set, invalidate entry and go through all listOfPrecursors and remove the unreachable 

	// destination from them: this is done via reverseListOfPrecursors

	// invalidate entry (dest seq nb was previously incremented while attempting to repair)
	// this function will also schedule deletion for the current entry
	if(DEBUG > 1) printf("    - Invalidate entry\n");
	aodv_entry_invalidate(indexEntryError->dest, indexEntryError->destSeqNb, n_flag);
	if(DEBUG > 1 ) printf("      > Remove unreachable node from all the precursor lists\n");

	aodv_listOfPrecursors_node_remove(indexEntryError->dest);
	}
// add the new unreachable destination to the RERR packet

if(DEBUG > 1 ) printf("      > Add destination to RERR packet\n");

// add destination to the list of new unreachable destinations 
aodv_listOfUnreachableDest_insert(newErrorStructPtr, indexEntryError->dest, indexEntryError->destSeqNb);

// If non_delete flag is not set, process the rest of routingTable entries:
// go through all entries, and process only those whos nextHop is the unreachable node
if(DEBUG > 1) printf("    - Look for other lost destinations\n");
if(n_flag == 0)
	{
	for(i=0;i<getFifoSize(routingTable);i++)

		{
		// read entry

		indexEntryError = (RoutingTableEntry*)(object->data);
		// Proceed only if the unreachable node is the next hop for this destination
		if(indexEntryError->nextHop == unreachableNode && indexEntryError->dest != unreachableNode) 
			{
			// read entry 
			unreachableDest = indexEntryError->dest;
			unreachableDestSeqNb = indexEntryError->destSeqNb;
			
			// invalidate entry
			if(DEBUG > 1) printf("    >  Ivalidate entry %d\n",unreachableDest);
			// invalidate entry and schedule deletion
			aodv_entry_invalidate(unreachableDest, unreachableDestSeqNb+1, n_flag);
			// go through all listOfPrecursors and remove the unreachable 

			// destination from them: this is done via reverseListOfPrecursors

			if(DEBUG > 1 ) printf("      > Remove unreachable node from all the precursor lists\n");

			aodv_listOfPrecursors_node_remove(unreachableDest);
			// add the new unreachable destination to the RERR packet

			if(DEBUG > 1 ) printf("      > Add destination to RERR packet\n");

			// add destination to the list of new unreachable destinations 
			aodv_listOfUnreachableDest_insert(newErrorStructPtr, unreachableDest, unreachableDestSeqNb);
			// print entry
			if(DEBUG) aodv_entryPtr_print(indexEntryError);
			}
		else
			if(DEBUG > 1) printf("      > skip entry %d\n",indexEntryError->dest);
		
		object=object->next;
		}

	
}

// if list of unreachable destinations is not empty, then 
// generate a RERR packet.
if(getFifoSize(newErrorStructPtr->listOfUnreachableDest)>0)


	{
	// Create RERR packet
	rerr_pk_ptr = op_pk_create_fmt("AODV_RERR");
	// Set N field value
	op_pk_nfd_set(rerr_pk_ptr,"N", n_flag);

	// Set the error structure and add it to packet
	newErrorStructPtr->destCount = getFifoSize(newErrorStructPtr->listOfUnreachableDest);
	op_pk_nfd_set(rerr_pk_ptr,"ErrorContent",newErrorStructPtr,op_prg_mem_copy_create,op_prg_mem_free,sizeof(ErrorContentStruct));

	if(DEBUG > 1) printf("      > RERR packet has been generated\n");

	// Send to mac Layer 
	aodv_pk_send_to_mac_layer(rerr_pk_ptr, BROADCAST);
	}
else
	{
	if(DEBUG > 1) printf("      > No unreachable destination caused by link breakage\n");

	}
	

if(DEBUG > 1) printf("    - Function aodv_rerr_pk_generate done !\n");

}


/*****************************************************************/

/************************ handle link breakage  ******************/

/*****************************************************************/


void 
aodv_link_repair_attempt(int dest, int ttl_src)

{

// vars
RoutingTableEntry* entryPtr;
int                TTL_REQUEST;

/*
/* This function checks whether the lost link
/* is repairable or not. If so, it generates a 
/* RREQ with the appropriate TTL. Else, it 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -