📄 dymo_packet_queue.ex.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 + -