750 lines
22 KiB
C
750 lines
22 KiB
C
/*
|
|
******************************************************************************
|
|
* INTERPEAK SOURCE FILE
|
|
*
|
|
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipnet_peer_info.c,v $ $Revision: 1.5.10.8 $
|
|
* $Source: /home/interpeak/CVSRoot/ipnet2/src/ipnet_peer_info.c,v $
|
|
* $Author: jren $
|
|
* $State: Exp $ $Locker: $
|
|
*
|
|
* INTERPEAK_COPYRIGHT_STRING
|
|
* Design and implementation by Kenneth Jonsson <kjonsson@windriver.com>
|
|
******************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 1 DESCRIPTION
|
|
****************************************************************************
|
|
*
|
|
* Implementation of IP peer information.
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 2 CONFIGURATION
|
|
****************************************************************************
|
|
*/
|
|
|
|
#include "ipnet_config.h"
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 3 INCLUDE FILES
|
|
****************************************************************************
|
|
*/
|
|
|
|
#define IPCOM_USE_CLIB_PROTO
|
|
#include <ipcom_clib.h>
|
|
#include <ipcom_cstyle.h>
|
|
#include <ipcom_list.h>
|
|
#include <ipcom_slab.h>
|
|
#include <ipcom_syslog.h>
|
|
#include <ipcom_type.h>
|
|
|
|
#include "ipnet_h.h"
|
|
#include "ipnet_peer_info.h"
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 4 DEFINES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
* Number of buckets in the "ipnet_peer_info_buckets" list
|
|
*/
|
|
#define IPNET_PEER_INFO_BUCKET_CNT 64
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 5 TYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 6 EXTERN PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 7 LOCAL PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 8 DATA
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
* Array of list heads. This pointer points to shared memory if the
|
|
* system is built as a NAE
|
|
*/
|
|
static Ipcom_list *ipnet_peer_info_buckets;
|
|
|
|
#ifndef IPCOM_FORWARDER_NAE
|
|
/*
|
|
* Slab cache for Ipnet_peer_info objects.
|
|
*/
|
|
static Ipcom_memory_cache *ipnet_peer_info_slab;
|
|
#endif
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 9 STATIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipnet_peer_info_key_hash
|
|
*===========================================================================
|
|
* Description: Returns a hash value for the lookup key.
|
|
* Parameters: vr - virtual router index.
|
|
* domain - address domain, IP_AF_INET or IP_AF_INET6
|
|
* addr - pointer to the IP address
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC unsigned
|
|
ipnet_peer_info_key_hash(Ip_u16 vr, int domain, const void *addr)
|
|
{
|
|
return ipcom_hash_update(addr,
|
|
(int)ipnet_ipaddrlen(domain),
|
|
(vr << 16) + domain) % IPNET_PEER_INFO_BUCKET_CNT;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipnet_peer_info_cmp_hash
|
|
*===========================================================================
|
|
* Description: Returns if the peer information object matches the
|
|
* search key.
|
|
* Parameters: vr - virtual router index.
|
|
* domain - address domain, IP_AF_INET or IP_AF_INET6
|
|
* addr - address of the peer
|
|
* peer_info - a peer information object
|
|
* Returns: IP_TRUE if the object matches the key
|
|
*
|
|
*/
|
|
IP_STATIC Ip_bool
|
|
ipnet_peer_info_cmp_hash(Ip_u16 vr,
|
|
int domain,
|
|
const void *addr,
|
|
const Ipnet_peer_info *peer_info)
|
|
{
|
|
return peer_info->vr == vr
|
|
&& peer_info->domain == domain
|
|
&& 0 == ipcom_memcmp(&peer_info->addr,
|
|
addr,
|
|
ipnet_ipaddrlen(domain));
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipnet_peer_info_malloc
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ipnet_peer_info *
|
|
ipnet_peer_info_malloc(void)
|
|
{
|
|
#ifdef IPCOM_FORWARDER_NAE
|
|
return ipcom_shm_malloc(sizeof(Ipnet_peer_info));
|
|
#else
|
|
return ipcom_slab_alloc(ipnet_peer_info_slab);
|
|
#endif
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipnet_peer_info_free
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters: peer_info -
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC void
|
|
ipnet_peer_info_free(Ipnet_peer_info *peer_info)
|
|
{
|
|
if (peer_info)
|
|
{
|
|
#ifdef IPCOM_FORWARDER_NAE
|
|
ipcom_shm_free(peer_info);
|
|
#else
|
|
ipcom_slab_free(ipnet_peer_info_slab, peer_info);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 10 GLOBAL FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
#if defined(IPCOM_FORWARDER_NAE)
|
|
|
|
#define IPNET_PEER_INFO_TIMEOUT_INFINITY (~(Ip_s64)0)
|
|
|
|
IP_GLOBAL void
|
|
ipnet_peer_info_timeout_schedule(Ipnet_peer_info *peer_info, Ip_s64 msec)
|
|
{
|
|
Ipcom_list *head = peer_info->list.head;
|
|
Ipnet_peer_info *p;
|
|
|
|
msec += ipnet->msec_now;
|
|
if (IP_UNLIKELY(IPNET_PEER_INFO_TIMEOUT_INFINITY == msec))
|
|
msec--;
|
|
|
|
peer_info->msec = msec;
|
|
|
|
/* Sort it into the list at its appropriate place */
|
|
ipcom_list_remove(&peer_info->list);
|
|
p = IPCOM_LIST_FIRST(head);
|
|
for (;;)
|
|
{
|
|
if (p == IP_NULL)
|
|
{
|
|
ipcom_list_insert_last(head, &peer_info->list);
|
|
break;
|
|
}
|
|
else if (peer_info->msec <= p->msec)
|
|
{
|
|
ipcom_list_insert_before(&p->list, &peer_info->list);
|
|
break;
|
|
}
|
|
|
|
p = IPCOM_LIST_NEXT(&p->list);
|
|
}
|
|
}
|
|
|
|
IP_GLOBAL void
|
|
ipnet_peer_info_timeout_cancel(Ipnet_peer_info *peer_info)
|
|
{
|
|
if (IPNET_PEER_INFO_TIMEOUT_INFINITY != peer_info->msec)
|
|
{
|
|
Ipcom_list *head = peer_info->list.head;
|
|
|
|
peer_info->msec = IPNET_PEER_INFO_TIMEOUT_INFINITY;
|
|
|
|
/* Move it last in the list; only active timer must be at the front */
|
|
ipcom_list_remove(&peer_info->list);
|
|
ipcom_list_insert_last(head, &peer_info->list);
|
|
}
|
|
}
|
|
|
|
IP_GLOBAL void
|
|
ipnet_peer_info_timeout_process(void)
|
|
{
|
|
Ipcom_list *head;
|
|
Ipnet_peer_info *peer_info;
|
|
unsigned idx;
|
|
|
|
ipcom_enter_critical_region();
|
|
|
|
for (idx = 0; idx < IPNET_PEER_INFO_BUCKET_CNT; idx++)
|
|
{
|
|
head = &ipnet_peer_info_buckets[idx];
|
|
|
|
for (;;)
|
|
{
|
|
peer_info = IPCOM_LIST_FIRST(head);
|
|
|
|
if (IP_NULL != peer_info
|
|
&& peer_info->msec != IPNET_PEER_INFO_TIMEOUT_INFINITY
|
|
&& IPCOM_IS_GEQ64(ipnet->msec_now, peer_info->msec))
|
|
{
|
|
Ip_s64 msec = peer_info->msec;
|
|
Ipcom_pkt *pkt = peer_info->reassembly_list;
|
|
Ip_u32 tag = IPCOM_PKT_GET_TAG(pkt);
|
|
|
|
/* Do not loose the peer info - We have a gap in the critsect - tag- critsect switch */
|
|
++peer_info->refcnt;
|
|
|
|
/* Exit the critical region */
|
|
ipcom_exit_critical_region();
|
|
|
|
/* Go atomic on the peer info tag */
|
|
ipcom_nae_switch_to_atomic(tag);
|
|
|
|
/* Re-enter the critical region */
|
|
ipcom_enter_critical_region();
|
|
|
|
/*
|
|
* Validate that we didnt loose the timeout during locking -
|
|
* 1 - We must have a reassembly list, with the same head
|
|
* 2 - We must have the same timeout tag
|
|
* 3 - We must have the same timeout value
|
|
* -
|
|
* If either fail; something was modified under us - Abort
|
|
* and retry. The peer_info structure is referenced, so we
|
|
* are safe that its still a valid pointer.
|
|
*/
|
|
if (peer_info->reassembly_list == pkt
|
|
&& tag == IPCOM_PKT_GET_TAG(pkt)
|
|
&& msec == peer_info->msec)
|
|
{
|
|
/* Unhook the reassembly list that cause the timeout */
|
|
peer_info->reassembly_list = pkt->next;
|
|
|
|
/* Cancel this timer */
|
|
ipnet_peer_info_timeout_cancel(peer_info);
|
|
|
|
/* Exit the critical region */
|
|
ipcom_exit_critical_region();
|
|
|
|
#ifdef IPCOM_USE_INET
|
|
/* Invoke */
|
|
if (peer_info->domain == IP_AF_INET)
|
|
ipnet_ip4_fragment_timeout_peer(peer_info, pkt);
|
|
#endif
|
|
#ifdef IPCOM_USE_INET6
|
|
/* Invoke */
|
|
if (peer_info->domain == IP_AF_INET6)
|
|
ipnet_ip6_fragment_timeout_peer(peer_info, pkt);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
/* Exit the critical region */
|
|
ipcom_exit_critical_region();
|
|
}
|
|
|
|
/* Go ordered on the peer info tag */
|
|
ipcom_nae_switch_to_ordered(tag);
|
|
|
|
/* Kill the timer manager reference */
|
|
ipnet_peer_info_release(peer_info);
|
|
|
|
/* Re-acquire the lock */
|
|
ipcom_enter_critical_region();
|
|
}
|
|
else
|
|
{
|
|
/* Done with this bucket */
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Exit the critical region */
|
|
ipcom_exit_critical_region();
|
|
}
|
|
|
|
|
|
#else
|
|
|
|
#ifdef IPNET_DEBUG
|
|
IP_STATIC int
|
|
ipnet_peer_info_fragment_tmo_to_string(Ipcom_pkt *frag_head, char *buf, int buf_len)
|
|
{
|
|
Ipnet_peer_info *peer_info;
|
|
|
|
peer_info = ipnet_frag_to_peer_info(frag_head);
|
|
|
|
#ifdef IPCOM_USE_INET
|
|
if (peer_info->domain == IP_AF_INET)
|
|
{
|
|
Ipnet_pkt_ip *iphdr;
|
|
char dst[IP_INET_ADDRSTRLEN];
|
|
char src[IP_INET_ADDRSTRLEN];
|
|
|
|
iphdr = ipcom_pkt_get_iphdr(frag_head);
|
|
return ipcom_snprintf(buf,
|
|
buf_len,
|
|
"IPv4 fragment id %d src %s dst %s",
|
|
ip_ntohs(iphdr->id),
|
|
ipcom_inet_ntop(IP_AF_INET, iphdr->src, src, sizeof(src)),
|
|
ipcom_inet_ntop(IP_AF_INET, iphdr->dst, dst, sizeof(dst)));
|
|
}
|
|
#endif
|
|
#ifdef IPCOM_USE_INET6
|
|
if (peer_info->domain == IP_AF_INET6)
|
|
{
|
|
Ip_pkt_ip6_frag *frag_hdr;
|
|
Ipnet_pkt_ip6 *ip_hdr;
|
|
char dst[IP_INET6_ADDRSTRLEN];
|
|
char src[IP_INET6_ADDRSTRLEN];
|
|
|
|
ip_hdr = ipcom_pkt_get_iphdr(frag_head);
|
|
frag_hdr = ipcom_pkt_get_data(frag_head, -(int)IP_IP6F_SIZE);
|
|
return ipcom_snprintf(buf,
|
|
buf_len,
|
|
"IPv6 fragment id %u src %s dst %s",
|
|
(unsigned) ip_ntohl(frag_hdr->ip6f_ident),
|
|
ipcom_inet_ntop(IP_AF_INET6, &ip_hdr->src, src, sizeof(src)),
|
|
ipcom_inet_ntop(IP_AF_INET6, &ip_hdr->dst, dst, sizeof(dst)));
|
|
}
|
|
#endif
|
|
|
|
return ipcom_snprintf(buf,
|
|
buf_len,
|
|
"IPvX fragment domain unknown");
|
|
}
|
|
#endif /* IPNET_DEBUG */
|
|
|
|
|
|
IP_STATIC void
|
|
ipnet_peer_info_fragment_timeout(Ipcom_pkt *frag_head)
|
|
{
|
|
Ipnet_peer_info *peer_info;
|
|
|
|
/*
|
|
* Unhook the fragment list from the reassembly list
|
|
*
|
|
* THIS FUNCTION IS ONLY INVOKED IN NON-NAE MODE - DO NOT NEED
|
|
* TO PROTECT THE REASSEMBLY LIST
|
|
*/
|
|
peer_info = ipnet_frag_to_peer_info(frag_head);
|
|
ip_assert(peer_info->reassembly_list == frag_head);
|
|
peer_info->reassembly_list = frag_head->next;
|
|
|
|
#ifdef IPCOM_USE_INET
|
|
/* Invoke */
|
|
if (peer_info->domain == IP_AF_INET)
|
|
ipnet_ip4_fragment_timeout_peer(peer_info, frag_head);
|
|
#endif
|
|
#ifdef IPCOM_USE_INET6
|
|
/* Invoke */
|
|
if (peer_info->domain == IP_AF_INET6)
|
|
ipnet_ip6_fragment_timeout_peer(peer_info, frag_head);
|
|
#endif
|
|
}
|
|
|
|
|
|
IP_GLOBAL void
|
|
ipnet_peer_info_timeout_schedule(Ipnet_peer_info *peer_info, Ip_s64 msec)
|
|
{
|
|
/* Clear anything thats pending */
|
|
ipnet_peer_info_timeout_cancel(peer_info);
|
|
|
|
/* Schedule a new one */
|
|
(void) ipnet_timeout_schedule(msec,
|
|
(Ipnet_timeout_handler) ipnet_peer_info_fragment_timeout,
|
|
peer_info->reassembly_list,
|
|
&peer_info->ptmo);
|
|
}
|
|
|
|
IP_GLOBAL void
|
|
ipnet_peer_info_timeout_cancel(Ipnet_peer_info *peer_info)
|
|
{
|
|
ipnet_timeout_cancel(peer_info->ptmo);
|
|
}
|
|
|
|
#endif
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipnet_peer_info_get
|
|
*===========================================================================
|
|
* Description: Returns a peer information entry matching the domain
|
|
* and address. The entry will be created if it does not
|
|
* already exist.
|
|
* Parameters: vr - virtual router index
|
|
* domain - IP_AF_INET or IP_AF_INET6
|
|
* addr - pointer to an IP address in domain 'domain'
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL Ipnet_peer_info *
|
|
ipnet_peer_info_get(Ip_u16 vr, int domain, const void *addr)
|
|
{
|
|
Ipcom_list *head;
|
|
Ipnet_peer_info *peer_info;
|
|
Ipnet_peer_info *new_peer_info = IP_NULL;
|
|
unsigned idx;
|
|
int i;
|
|
|
|
idx = ipnet_peer_info_key_hash(vr, domain, addr);
|
|
|
|
recheck:
|
|
ipcom_enter_critical_region();
|
|
head = &ipnet_peer_info_buckets[idx];
|
|
|
|
/*
|
|
* Check if the entry already exist
|
|
*/
|
|
for (peer_info = IPCOM_LIST_FIRST(head);
|
|
peer_info != IP_NULL;
|
|
peer_info = IPCOM_LIST_NEXT(&peer_info->list))
|
|
{
|
|
if (ipnet_peer_info_cmp_hash(vr, domain, addr, peer_info))
|
|
{
|
|
++peer_info->refcnt;
|
|
ipcom_exit_critical_region();
|
|
ipnet_peer_info_free(new_peer_info);
|
|
return peer_info;
|
|
}
|
|
}
|
|
|
|
if (new_peer_info == IP_NULL)
|
|
{
|
|
/*
|
|
* Must allocate memory outside of the critical region to
|
|
* avoid deadlock. Must retry to find the entry since another
|
|
* NAE might have added while this NAE is running outside of
|
|
* the critical region.
|
|
*/
|
|
ipcom_exit_critical_region();
|
|
new_peer_info = ipnet_peer_info_malloc();
|
|
if (new_peer_info == IP_NULL)
|
|
return IP_NULL;
|
|
goto recheck;
|
|
}
|
|
|
|
/*
|
|
* No peer information found, create a new entry
|
|
*/
|
|
peer_info = new_peer_info;
|
|
peer_info->refcnt = 1;
|
|
peer_info->vr = vr;
|
|
peer_info->domain = domain;
|
|
peer_info->reassembly_list = IP_NULL;
|
|
peer_info->flags = 0;
|
|
ipcom_memcpy(&peer_info->addr, addr, ipnet_ipaddrlen(domain));
|
|
ipcom_atomic_set(&peer_info->id, ipcom_rand());
|
|
#ifdef IPCOM_USE_INET
|
|
if (ipnet->conf.inet.random_ip_id)
|
|
#endif
|
|
{
|
|
for (i = 0; i < IPNET_PEER_INFO_ID_CNT; i++)
|
|
ipcom_atomic_set(&peer_info->ids[i], ipcom_rand());
|
|
}
|
|
ipcom_list_insert_last(head, &peer_info->list);
|
|
|
|
#if defined(IPCOM_FORWARDER_NAE)
|
|
peer_info->msec = IPNET_PEER_INFO_TIMEOUT_INFINITY;
|
|
#else
|
|
peer_info->ptmo = IP_NULL;
|
|
#endif
|
|
|
|
|
|
ipcom_exit_critical_region();
|
|
|
|
return peer_info;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipnet_peer_info_addref
|
|
*===========================================================================
|
|
* Description: Increases the reference count on a peer information entry
|
|
* Parameters: peer_info - a peer information entry
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL void
|
|
ipnet_peer_info_addref(Ipnet_peer_info *peer_info)
|
|
{
|
|
ipcom_enter_critical_region();
|
|
ip_assert(peer_info->refcnt > 0);
|
|
++peer_info->refcnt;
|
|
ipcom_exit_critical_region();
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipnet_peer_info_release
|
|
*===========================================================================
|
|
* Description: Releases a reference to a peer information entry
|
|
* Parameters: peer_info - a peer information entry.
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL void
|
|
ipnet_peer_info_release(Ipnet_peer_info *peer_info)
|
|
{
|
|
ipcom_enter_critical_region();
|
|
|
|
ip_assert(peer_info->refcnt > 0);
|
|
if (--peer_info->refcnt > 0)
|
|
ipcom_exit_critical_region();
|
|
else
|
|
{
|
|
Ipcom_pkt *pkt;
|
|
Ipcom_pkt *reassembly_list = peer_info->reassembly_list;
|
|
|
|
ipcom_list_remove(&peer_info->list);
|
|
|
|
ipcom_exit_critical_region();
|
|
|
|
/*
|
|
* Free all fragments of partially reassembled packets
|
|
*/
|
|
while (IP_NULL != (pkt = reassembly_list))
|
|
{
|
|
reassembly_list = pkt->next;
|
|
ipcom_pkt_free(pkt);
|
|
}
|
|
ipnet_peer_info_free(peer_info);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipnet_peer_info_init
|
|
*===========================================================================
|
|
* Description: Initializes the peer information database.
|
|
* Parameters:
|
|
* Returns: 0 = success
|
|
* -IP_ERRNO_ENOMEM = out of memory
|
|
*
|
|
*/
|
|
IP_GLOBAL int
|
|
ipnet_peer_info_init(void)
|
|
{
|
|
unsigned i;
|
|
|
|
#ifdef IPCOM_FORWARDER_NAE
|
|
Ipnet_shm *shm = ipcom_shm_component(IPCOM_LOG_IPNET, sizeof(*shm));
|
|
|
|
if (!shm->is_initialized)
|
|
{
|
|
shm->peer_info_buckets
|
|
= ipcom_shm_reserve(IPNET_PEER_INFO_BUCKET_CNT
|
|
* sizeof(Ipcom_list));
|
|
|
|
for (i = 0; i < IPNET_PEER_INFO_BUCKET_CNT; i++)
|
|
ipcom_list_init(&shm->peer_info_buckets[i]);
|
|
}
|
|
|
|
/*
|
|
* else: another NAE has already initialized the shared memory
|
|
* region. This NAE should just point into the already initialized
|
|
* area.
|
|
*/
|
|
|
|
ipnet_peer_info_buckets = shm->peer_info_buckets;
|
|
|
|
#else
|
|
ipnet_peer_info_buckets = ipcom_calloc(IPNET_PEER_INFO_BUCKET_CNT,
|
|
sizeof(Ipcom_list));
|
|
|
|
ipnet_peer_info_slab = ipcom_slab_new("IPNET peer information",
|
|
0,
|
|
sizeof(Ipnet_peer_info),
|
|
0,
|
|
IP_NULL,
|
|
IP_NULL,
|
|
ipnet->memory_pool);
|
|
|
|
if (ipnet_peer_info_buckets == IP_NULL
|
|
|| ipnet_peer_info_slab == IP_NULL)
|
|
return -IP_ERRNO_ENOMEM;
|
|
|
|
for (i = 0; i < IPNET_PEER_INFO_BUCKET_CNT; i++)
|
|
ipcom_list_init(&ipnet_peer_info_buckets[i]);
|
|
|
|
|
|
#ifdef IPNET_DEBUG
|
|
ipnet_timeout_to_string((Ipnet_timeout_handler) ipnet_peer_info_fragment_timeout,
|
|
(Ipnet_timeout_to_string_f) ipnet_peer_info_fragment_tmo_to_string);
|
|
|
|
#endif /* !IPCOM_FORWARDER_NAE */
|
|
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
#ifdef IPNET_USE_SHOW
|
|
/*
|
|
*===========================================================================
|
|
* ipnet_peer_info_show
|
|
*===========================================================================
|
|
* Description: Dumps a single peer info entry to the console.
|
|
* Parameters: peer_info - a peer info entry.
|
|
* unused - unused.
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC void
|
|
ipnet_peer_info_show(Ipnet_peer_info *peer_info, void *unused)
|
|
{
|
|
char addr_str[IP_INET6_ADDRSTRLEN];
|
|
|
|
IPCOM_UNUSED_ARG(unused);
|
|
ipcom_printf("%-6u %-30s %-10d %-4u\n",
|
|
peer_info->vr,
|
|
ipcom_inet_ntop(peer_info->domain,
|
|
&peer_info->addr,
|
|
addr_str,
|
|
sizeof(addr_str)),
|
|
(unsigned) ((peer_info->domain == IP_AF_INET
|
|
? 0xffff
|
|
: ~0)
|
|
& ipcom_atomic_get(&peer_info->id)),
|
|
peer_info->refcnt);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* peerInfoShow
|
|
*===========================================================================
|
|
* Description: Dumps all peer info entries to the console
|
|
* Parameters:
|
|
* Returns: Number of entries dumped.
|
|
*
|
|
*/
|
|
int peerInfoShow(void);
|
|
int peerInfoShow(void)
|
|
{
|
|
unsigned i;
|
|
int cnt = 0;
|
|
Ipcom_list *node;
|
|
Ipnet_peer_info *peer_info;
|
|
|
|
ipcom_printf("%-6s %-30s %-10s %-4s\n", "VR", "Address", "ID", "RefCnt");
|
|
|
|
for (i = 0; i < IPNET_PEER_INFO_BUCKET_CNT; i++)
|
|
for (node = ipcom_list_first(&ipnet_peer_info_buckets[i]);
|
|
node != IP_NULL;
|
|
node = ipcom_list_next(node))
|
|
{
|
|
peer_info = ipcom_list_entry(node, Ipnet_peer_info, list);
|
|
ipnet_peer_info_show(peer_info, IP_NULL);
|
|
cnt++;
|
|
}
|
|
|
|
return cnt;
|
|
}
|
|
#endif /* IPNET_USE_SHOW */
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 11 PUBLIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* END OF FILE
|
|
****************************************************************************
|
|
*/
|
|
|