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

📄 dymo_packet_queue.ex.c

📁 备
💻 C
字号:
/* dymo_packet_queue.ex.c */
/* C file for DYMO Packet Queue APIs */


/****************************************/
/*		Copyright (c) 1987-2003			*/
/*		by OPNET Technologies, Inc.		*/
/*		(A Delaware Corporation)		*/
/*	7255 Woodmont Av., Suite 250  		*/
/*     Bethesda, MD 20814, U.S.A.       */
/*			All Rights Reserved.		*/
/****************************************/

/***** Includes *****/
#include <opnet.h>
#include <dymo.h>
#include <dymo_ptypes.h>
#include <manet.h>
#include <ip_addr_v4.h>

/***** Prototypes *****/
static void						dymo_packet_queue_oldest_entry_delete (DymoT_Packet_Queue*);
static void						dymo_packet_queue_size_stat_update (DymoT_Packet_Queue*);
static void						dymo_packet_queue_route_discovery_time_stat_update (DymoT_Packet_Queue*, List*);
static DymoT_Packet_Queue*		dymo_packet_queue_mem_alloc (void);
static DymoT_Packet_Entry*		dymo_packet_queue_entry_mem_alloc (void);
static void						dymo_packet_queue_entry_mem_free (DymoT_Packet_Entry*);


DymoT_Packet_Queue*
dymo_packet_queue_create (int size, DymoT_Local_Stathandles* local_stat_handles_ptr)
	{
	DymoT_Packet_Queue*		pkt_queue_ptr;
	
	/** Creates and allocates memory for	**/
	/** the packet queue which buffers data	**/
	/** packets while a route is being		**/
	/** discovered to the destination		**/
	FIN (dymo_packet_queue_create (<args>));
	
	pkt_queue_ptr = dymo_packet_queue_mem_alloc ();
	pkt_queue_ptr->max_queue_size = size;
	pkt_queue_ptr->stat_handle_ptr = local_stat_handles_ptr;
	
	FRET (pkt_queue_ptr);
	}
	

void
dymo_packet_queue_insert (DymoT_Packet_Queue* pkt_queue_ptr, Packet* data_pkptr, InetT_Address dest_addr)
	{
	List*					pkt_lptr;
	DymoT_Packet_Entry*		pkt_entry_ptr;
	char					dest_addr_str [INETC_ADDR_STR_LEN];
	void*					old_contents_ptr;
	
	/** Inserts a new data packet into the	**/
	/** packet queue. If the queue is full	**/
	/** the oldest packet in the queue is	**/
	/** dropped and the new packet inserted	**/
	FIN (dymo_packet_queue_insert (<args>));
	
	if ((pkt_queue_ptr->max_queue_size != DYMOC_INFINITE_PACKET_QUEUE) &&
		(pkt_queue_ptr->max_queue_size == pkt_queue_ptr->current_queue_size))
		{
		/* There is no more space in the queue to insert	*/
		/* any other packet. Delete the oldest packet in 	*/
		/* packet queue to make space for the new packet	*/
		dymo_packet_queue_oldest_entry_delete (pkt_queue_ptr);
		}
	
	/* Create the destination address string	*/
	inet_address_print (dest_addr_str, dest_addr);
	
	/* Check if there are already other packets */
	/* waiting for this destination.			*/
	pkt_lptr = (List*) prg_string_hash_table_item_get (pkt_queue_ptr->pkt_queue_table, dest_addr_str);
	
	if (pkt_lptr == OPC_NIL)
		{
		/* No entry exists for this destination	*/
		/* Create a new entry and insert in		*/
		pkt_lptr = op_prg_list_create ();
		prg_string_hash_table_item_insert (pkt_queue_ptr->pkt_queue_table, dest_addr_str, pkt_lptr, 
											&old_contents_ptr);
		}
	
	/* Allocate memory to store the new packet	*/
	pkt_entry_ptr = dymo_packet_queue_entry_mem_alloc ();
	pkt_entry_ptr->pkptr = data_pkptr;
	pkt_entry_ptr->insert_time = op_sim_time ();
	
	/* Always insert at the tail of the list so	*/
	/* that the oldest packets are at the head 	*/
	/* of the list automatically				*/
	op_prg_list_insert (pkt_lptr, pkt_entry_ptr, OPC_LISTPOS_TAIL);
	pkt_queue_ptr->current_queue_size++;
	
	/* Update the packet queue size statistic	*/
	dymo_packet_queue_size_stat_update (pkt_queue_ptr);
	
	FOUT;
	}


List*
dymo_packet_queue_all_pkts_to_dest_get (DymoT_Packet_Queue* pkt_queue_ptr, InetT_Address dest_addr, 
											Boolean remove, Boolean update_discovery_time_stat)
	{
	DymoT_Packet_Entry*		pkt_entry_ptr;
	List*					pkt_lptr;
	List*					data_pkt_lptr;
	char					dest_addr_str [INETC_ADDR_STR_LEN];
	int						num_pkts, count;
	
	/** Based on the input flag either access or	**/
	/** remove packets from the queue 				**/
	FIN (dymo_packet_queue_all_pkts_to_dest_get (<args>));
	
	/* Create the destination address string	*/
	inet_address_print (dest_addr_str, dest_addr);
	
	
	/* Based on the input flag either just access	*/
	/* or remove the packets from the packet queue	*/
	if (remove)
		{
		/* Remove the packets from the queue	*/
		data_pkt_lptr = (List*) prg_string_hash_table_item_remove (pkt_queue_ptr->pkt_queue_table, dest_addr_str);
		
		/* Return if there's no packet to remove */
		if (data_pkt_lptr == OPC_NIL)
			FRET (OPC_NIL);
		
		if (update_discovery_time_stat)
			{
			/* Write the statistic for the route discovery	*/
			/* time for this destination.					*/
			dymo_packet_queue_route_discovery_time_stat_update (pkt_queue_ptr, data_pkt_lptr);
			}
		
		if (op_prg_list_size (data_pkt_lptr) > 0)
			{
			/* Update the packet queue size statistic	*/
			dymo_packet_queue_size_stat_update (pkt_queue_ptr);
			}
		
		pkt_queue_ptr->current_queue_size -= op_prg_list_size (data_pkt_lptr);
		
		}
	else
		{
		/* Only access the packets in the queue	*/
		pkt_lptr = (List*) prg_string_hash_table_item_get (pkt_queue_ptr->pkt_queue_table, dest_addr_str);

		/* Create a list to return the packets	*/
		data_pkt_lptr = op_prg_list_create ();

		num_pkts = op_prg_list_size (pkt_lptr);
		
		for (count = 0; count < num_pkts; count++)
			{
			pkt_entry_ptr = (DymoT_Packet_Entry*) op_prg_list_access (pkt_lptr, count);
			op_prg_list_insert (data_pkt_lptr, pkt_entry_ptr->pkptr, OPC_LISTPOS_TAIL);
			}
		}
	
	FRET (data_pkt_lptr);
	}


int
dymo_packet_queue_num_pkts_get (DymoT_Packet_Queue* pkt_queue_ptr, InetT_Address dest_addr)
	{
	List*					pkt_lptr;
	char					dest_addr_str [INETC_ADDR_STR_LEN];
	
	FIN (dymo_packet_queue_num_pkts_get (<args>));
	
	/* Create the destination address string	*/
	inet_address_print (dest_addr_str, dest_addr);
	
	/* Only access the packets in the queue	*/
	pkt_lptr = (List*) prg_string_hash_table_item_get (pkt_queue_ptr->pkt_queue_table, dest_addr_str);

	if (pkt_lptr == OPC_NIL)
		{
		FRET (0);
		}
	else
		{
		FRET (op_prg_list_size (pkt_lptr));
		}	  
	}
		
	
	
void
dymo_packet_queue_all_pkts_to_dest_delete (DymoT_Packet_Queue* pkt_queue_ptr, InetT_Address dest_addr)
	{
	DymoT_Packet_Entry*			pkt_entry_ptr;
	DymoT_Global_Stathandles*	global_stathandle_ptr = OPC_NIL;
	List*						pkt_lptr;
	char						dest_addr_str [INETC_ADDR_STR_LEN];
	int							num_pkts;
	
	/** Deletes all packets to a specific destination	**/
	FIN (dymo_packet_queue_all_pkts_to_dest_delete (<args>));
	
	/* Create the destination address string	*/
	inet_address_print (dest_addr_str, dest_addr);
	
	/* Remove the packets form the queue	*/
	pkt_lptr = (List*) prg_string_hash_table_item_remove (pkt_queue_ptr->pkt_queue_table, dest_addr_str);
	
	if (pkt_lptr == OPC_NIL)
		FOUT;
	
	/* Decrement the size of the queue	*/
	num_pkts = op_prg_list_size (pkt_lptr);
	pkt_queue_ptr->current_queue_size -= num_pkts;
	
	/* Update the packet queue size statistic	*/
	dymo_packet_queue_size_stat_update (pkt_queue_ptr);
	
	/* Update the number of packets dropped statistic	*/
	op_stat_write (pkt_queue_ptr->stat_handle_ptr->num_pkts_discard_shandle, (double) num_pkts);
	
	/* Get a handle to the global statistics	*/
	global_stathandle_ptr = dymo_support_global_stat_handles_obtain ();
	
	/* Update the global statistic for the number of pkts dropped	*/
	op_stat_write (global_stathandle_ptr->num_pkts_discard_global_shandle, (double) num_pkts);
	
	/* Free each entry in the list	*/
	while (num_pkts > 0)
		{
		pkt_entry_ptr = (DymoT_Packet_Entry*) op_prg_list_remove (pkt_lptr, OPC_LISTPOS_HEAD);
		dymo_packet_queue_entry_mem_free (pkt_entry_ptr);
		num_pkts--;
		}
	
	/* Free the list	*/
	op_prg_mem_free (pkt_lptr);
	
	FOUT;
	}


/*** Internally callable functions	***/

static void
dymo_packet_queue_oldest_entry_delete (DymoT_Packet_Queue* pkt_queue_ptr)
	{
	List*						keys_lptr;
	char*						key_str;
	int							num_keys, count;
	List*						pkt_lptr;
	DymoT_Packet_Entry*			pkt_entry_ptr;
	double						oldest_time = OPC_DBL_INFINITY;
	char*						oldest_key_str;
	DymoT_Global_Stathandles*	global_stathandle_ptr = OPC_NIL;
	
	/** Deletes the oldest entry in the packet list	**/
	FIN (dymo_packet_queue_oldest_entry_delete (<args>));
	
	/* Get all the destinations in the table	*/
	keys_lptr = prg_string_hash_table_keys_get (pkt_queue_ptr->pkt_queue_table);
	
	num_keys = op_prg_list_size (keys_lptr);
	
	for (count = 0; count < num_keys; count++)
		{
		/* Access each key which is a dest addr str	*/
		key_str = (char*) op_prg_list_access (keys_lptr, count);
		
		/* Access the element in the hash table for this key	*/
		pkt_lptr = (List*) prg_string_hash_table_item_get (pkt_queue_ptr->pkt_queue_table, key_str);
		
		/* Error check	*/
		if ((pkt_lptr == OPC_NIL) || (op_prg_list_size (pkt_lptr) == 0))
			continue;
		
		/* The first element in the list is the	*/
		/* oldest to this destination			*/
		pkt_entry_ptr = (DymoT_Packet_Entry*) op_prg_list_access (pkt_lptr, OPC_LISTPOS_HEAD);
		
		if (pkt_entry_ptr->insert_time < oldest_time)
			{
			/* This entry is the new oldest entry	*/
			oldest_time = pkt_entry_ptr->insert_time;
			oldest_key_str = key_str;
			}
		}
	
	/* Delete the oldest entry	*/
	pkt_lptr = (List*) prg_string_hash_table_item_get (pkt_queue_ptr->pkt_queue_table, oldest_key_str);
	pkt_entry_ptr = (DymoT_Packet_Entry*) op_prg_list_remove (pkt_lptr, OPC_LISTPOS_HEAD);
	dymo_packet_queue_entry_mem_free (pkt_entry_ptr);
	
	/* Update the number of packets dropped statistic	*/
	op_stat_write (pkt_queue_ptr->stat_handle_ptr->num_pkts_discard_shandle, 1.0);
	
	/* Get a handle to the global statistics	*/
	global_stathandle_ptr = dymo_support_global_stat_handles_obtain ();
	
	/* Update the global statistic for the number of pkts dropped	*/
	op_stat_write (global_stathandle_ptr->num_pkts_discard_global_shandle, 1.0);
	
	
	if (op_prg_list_size (pkt_lptr) == 0)
		{
		/* There are no more packets to the	*/
		/* destination. Delete the list		*/
		pkt_lptr = (List*) prg_string_hash_table_item_remove (pkt_queue_ptr->pkt_queue_table, oldest_key_str);
		op_prg_mem_free (pkt_lptr);
		}
		
	/* Decrement the size of the packet queue	*/
	pkt_queue_ptr->current_queue_size--;
	
	/* Update the packet queue size statistic	*/
	dymo_packet_queue_size_stat_update (pkt_queue_ptr);
	
	/* Free the keys	*/
	op_prg_list_free (keys_lptr);
	op_prg_mem_free (keys_lptr);
	
	FOUT;
	}


static void
dymo_packet_queue_route_discovery_time_stat_update (DymoT_Packet_Queue* pkt_queue_ptr, List* pkt_queue_lptr)
	{
	int							num_pkts, count;
	DymoT_Packet_Entry*			pkt_entry_ptr = OPC_NIL;
	DymoT_Global_Stathandles*	global_stathandle_ptr = OPC_NIL;
	double						first_enqueue_time = OPC_DBL_INFINITY;
	double						route_discovery_time;
	
	/** Updates the statistic for the route discovery time	**/
	FIN (dymo_packet_queue_route_discovery_time_stat_update (<args>));
	
	/* Get the number of packets for the	*/
	/* destination whose route has just 	*/
	/* been discovered						*/
	num_pkts = op_prg_list_size (pkt_queue_lptr);
	
	for (count = 0; count < num_pkts; count++)
		{
		/* Access each packet information	*/
		/* and determine the first packet	*/
		/* that was enqueued.				*/
		pkt_entry_ptr = (DymoT_Packet_Entry*) op_prg_list_access (pkt_queue_lptr, count);
		
		if (pkt_entry_ptr->insert_time < first_enqueue_time)
			{
			/* This entry is earlier than 	*/
			/* any other so far				*/
			first_enqueue_time = pkt_entry_ptr->insert_time;
		    }
		}
	
	/* The route discovery time is the time	*/
	/* difference between the first packet 	*/
	/* enqueued to this destination and the	*/
	/* current simulation time when the 	*/
	/* route was discovered					*/
	route_discovery_time = op_sim_time () - first_enqueue_time;
	
	/* Get a handle to the global statistics	*/
	global_stathandle_ptr = dymo_support_global_stat_handles_obtain ();
	
	/* Update the route discovery time for	*/
	/* a specific destination				*/
	op_stat_write (pkt_queue_ptr->stat_handle_ptr->route_discovery_time_shandle, route_discovery_time);
	
	/* Update the global route discovery time statistic	*/
	op_stat_write (global_stathandle_ptr->route_discovery_time_global_shandle, route_discovery_time);
	
	FOUT;
	}


static void
dymo_packet_queue_size_stat_update (DymoT_Packet_Queue* pkt_queue_ptr)
	{
	/** Updates the send buffer statistic	*/
	FIN (dymo_packet_queue_size_stat_update (<args>));
	
	/* Update the size of the send buffer local statistic	*/
	op_stat_write (pkt_queue_ptr->stat_handle_ptr->pkt_queue_size_shandle, (double) pkt_queue_ptr->current_queue_size);
	
	FOUT;
	}
		

static DymoT_Packet_Queue*
dymo_packet_queue_mem_alloc (void)
	{
	DymoT_Packet_Queue*		pkt_queue_ptr;
	
	/** Allocates memory for the packet queue	**/
	FIN (dymo_packet_queue_mem_alloc (void));
	
	pkt_queue_ptr = (DymoT_Packet_Queue*) op_prg_mem_alloc (sizeof (DymoT_Packet_Queue));
	pkt_queue_ptr->pkt_queue_table = (PrgT_String_Hash_Table*) prg_string_hash_table_create (10, 10);
	pkt_queue_ptr->current_queue_size = 0;
	pkt_queue_ptr->max_queue_size = 0;
	
	FRET (pkt_queue_ptr);
	}


static DymoT_Packet_Entry*
dymo_packet_queue_entry_mem_alloc (void)
	{
	static Pmohandle		packet_entry_pmh;
	DymoT_Packet_Entry*		packet_entry_ptr = OPC_NIL;
	static Boolean			packet_entry_pmh_defined = OPC_FALSE;
	
	/** Allocates pooled memory for every packet entry	**/
	FIN (dymo_packet_queue_entry_mem_alloc (void));
	
	if (packet_entry_pmh_defined == OPC_FALSE)
		{
		/* Define the pool memory handle for route table entry	*/
		packet_entry_pmh = op_prg_pmo_define ("Packet Queue Entry", sizeof (DymoT_Packet_Entry), 32);
		packet_entry_pmh_defined = OPC_TRUE;
		}
	
	/* Allocate the route table entry from the pooled memory	*/
	packet_entry_ptr = (DymoT_Packet_Entry*) op_prg_pmo_alloc (packet_entry_pmh);
	
	FRET (packet_entry_ptr);
	}

static void
dymo_packet_queue_entry_mem_free (DymoT_Packet_Entry* pkt_entry_ptr)
	{
	/** Frees the packet entry **/
	FIN (dymo_packet_queue_entry_mem_free (<args>));
	
	/* Destroy the packet	*/
	manet_rte_ip_pkt_destroy (pkt_entry_ptr->pkptr);
	op_prg_mem_free (pkt_entry_ptr);
	
	FOUT;
	}

⌨️ 快捷键说明

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