653 lines
18 KiB
C
653 lines
18 KiB
C
|
|
/*
|
|
******************************************************************************
|
|
* INTERPEAK SOURCE FILE
|
|
*
|
|
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmip_context.c,v $ $Revision: 1.16.16.1 $
|
|
* $Source: /home/interpeak/CVSRoot/ipmip/src/ipmip_context.c,v $
|
|
* $Author: jsheng $
|
|
* $State: Exp $ $Locker: $
|
|
*
|
|
* INTERPEAK_COPYRIGHT_STRING
|
|
* Design and implementation by Joel Hortelius <joel.hortelis@interpeak.se>
|
|
******************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 1 DESCRIPTION
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 2 CONFIGURATION
|
|
****************************************************************************
|
|
*/
|
|
|
|
#include <ipmip_config.h>
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 3 INCLUDE FILES
|
|
****************************************************************************
|
|
*/
|
|
#define IPCOM_USE_CLIB_PROTO
|
|
#include <ipcom_clib.h>
|
|
#include <ipcom_err.h>
|
|
#include <ipcom_hash.h>
|
|
#include <ipcom_inet.h>
|
|
#include <ipcom_ipd.h>
|
|
#include <ipcom_list.h>
|
|
#include <ipcom_os.h>
|
|
#include <ipcom_sock.h>
|
|
#include <ipcom_sock2.h>
|
|
#include <ipcom_syslog.h>
|
|
#include <ipcom_sysvar.h>
|
|
|
|
#include <ipmip.h>
|
|
#include <private/ipmip_sysvar.h>
|
|
#include <private/ipmip_util.h>
|
|
#include <private/ipmip_context.h>
|
|
#include <private/ipmip_pktbuf.h>
|
|
#include <private/ipmip_timer.h>
|
|
#include <private/ipmip_cli.h>
|
|
#include <private/ipmip_log.h>
|
|
#include <private/ipmip_dhcp.h>
|
|
#include <private/ipmip_inet.h>
|
|
#include <private/ipmip_dhcp6.h>
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 4 DEFINES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 5 TYPES
|
|
****************************************************************************
|
|
*/
|
|
struct Ipmip_context_id_hash_cb
|
|
{
|
|
Ipmip_util_hash_foreach_t func;
|
|
void *arg1;
|
|
void *arg2;
|
|
};
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 6 EXTERN PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 7 LOCAL PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 8 DATA
|
|
****************************************************************************
|
|
*/
|
|
/* Arguments */
|
|
static Ipcom_mutex ipmip_context_proc_lock;
|
|
static Ipmip_context_t *ipmip_context_thread_ctx = IP_NULL;
|
|
static Ipmip_proc_t *ipmip_context_thread_proc = IP_NULL;
|
|
static void *ipmip_context_thread_arg = IP_NULL;
|
|
static Ipmip_proc_func_t ipmip_context_thread_func = IP_NULL;
|
|
static Ipcom_once_t ipmip_context_once = IPCOM_ONCE_INIT;
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 9 STATIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
IP_STATIC unsigned
|
|
ipmip_context_id_hash(Ip_u32 *ko)
|
|
{
|
|
return ipcom_hash_update(ko, sizeof(*ko), 0);
|
|
}
|
|
|
|
IP_STATIC Ip_bool
|
|
ipmip_context_id_cmp(Ip_u32 *obj, Ip_u32 *key)
|
|
{
|
|
/* Compare */
|
|
return *obj == *key;
|
|
}
|
|
|
|
IP_STATIC void
|
|
ipmip_context_id_foreach_func(Ipmip_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
Ip_u8 *pident,
|
|
Ipmip_context_id_t *idctx,
|
|
struct Ipmip_context_id_hash_cb *cbinfo)
|
|
{
|
|
|
|
(*cbinfo->func) (ctx, proc, pident - idctx->identity_offset, cbinfo->arg1, cbinfo->arg2);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip_timer_setup
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ip_err
|
|
ipmip_context_setup(void *unused)
|
|
{
|
|
IPMIP_UNUSED_PARAMETER(unused);
|
|
|
|
(void)ipcom_mutex_create(&ipmip_context_proc_lock);
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
|
|
|
|
IP_STATIC
|
|
IPCOM_PROCESS(ipmip_proc)
|
|
{
|
|
Ipmip_proc_t *proc;
|
|
Ipmip_context_t *ctx;
|
|
void *arg;
|
|
Ipmip_proc_func_t func;
|
|
|
|
ipcom_proc_init();
|
|
|
|
/* Get the argument */
|
|
ctx = ipmip_context_thread_ctx;
|
|
proc = ipmip_context_thread_proc;
|
|
arg = ipmip_context_thread_arg;
|
|
func = ipmip_context_thread_func;
|
|
ipmip_context_thread_arg = IP_NULL;
|
|
ipmip_context_thread_proc = IP_NULL;
|
|
ipmip_context_thread_ctx = IP_NULL;
|
|
ipmip_context_thread_func = IP_NULL;
|
|
proc->pid = ipcom_getpid();
|
|
|
|
/* Release the start thread */
|
|
ipcom_block_post(proc->proc_block);
|
|
|
|
/* Invoke the callback */
|
|
(*func) (ctx, proc, arg);
|
|
|
|
/* Release the start thread */
|
|
ipcom_block_post(proc->proc_block);
|
|
|
|
/* */
|
|
ipcom_proc_exit();
|
|
}
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 10 GLOBAL FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip_context_alloc
|
|
*===========================================================================
|
|
* Description: Allocate the packet context
|
|
* Parameters: proc - Process context
|
|
* size - Total size of context.
|
|
* Returns: The newly allocated packet context on success.
|
|
*
|
|
*/
|
|
IP_GLOBAL Ipmip_context_t *
|
|
ipmip_context_alloc(Ipmip_proc_t *proc,
|
|
Ip_size_t size,
|
|
const char *name,
|
|
int loglevel,
|
|
int evsize)
|
|
{
|
|
Ipmip_context_t *ctx;
|
|
|
|
/* Initialize */
|
|
(void)IPMIP_ONCE(&ipmip_context_once, ipmip_context_setup, IP_NULL);
|
|
|
|
ctx = ipcom_calloc(1, size);
|
|
|
|
if (!ctx)
|
|
return IP_NULL;
|
|
|
|
#if IPCOM_VR_MAX > 1
|
|
ctx->vr = ipcom_proc_vr_get();
|
|
#endif
|
|
|
|
(void)ipcom_mutex_create(&ctx->log.events_lock);
|
|
ipcom_list_init(&ctx->log.events);
|
|
|
|
ipmip_log_loglevel(ctx, proc, loglevel);
|
|
ipmip_log_event_backlog(ctx, proc, evsize);
|
|
|
|
ctx->name = ipcom_strdup(name);
|
|
|
|
/* Request handle */
|
|
ctx->nl_req = ipmip_netlink_open(IP_NETLINK_ROUTE, 0);
|
|
|
|
/* Allocate an ioctl socket */
|
|
#ifdef IPMIP_USE_INET6
|
|
ctx->fd_ioctl = ipcom_socket(IP_AF_INET6, IP_SOCK_DGRAM, IP_IPPROTO_UDP);
|
|
#else
|
|
ctx->fd_ioctl = ipcom_socket(IP_AF_INET, IP_SOCK_DGRAM, IP_IPPROTO_UDP);
|
|
#endif
|
|
|
|
if (!ipmip_timer_context_create(ctx, proc))
|
|
goto fail;
|
|
|
|
|
|
return ctx;
|
|
fail:
|
|
ipmip_context_destroy(ctx, proc);
|
|
return IP_NULL;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip_context_start
|
|
*===========================================================================
|
|
* Description: Start the context
|
|
* Parameters: ctx - The context
|
|
* proc - Current thead context
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL void
|
|
ipmip_context_start(Ipmip_context_t *ctx,
|
|
Ipmip_proc_t *proc)
|
|
{
|
|
/* Start the context */
|
|
ipmip_timer_context_start(ctx, proc);
|
|
ipmip_cli_context_start(ctx, proc);
|
|
ipmip_netlink_context_start(ctx, proc);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip_context_stop
|
|
*===========================================================================
|
|
* Description: Stop the context
|
|
* Parameters: ctx - The context
|
|
* proc - Process context
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL void
|
|
ipmip_context_stop(Ipmip_context_t *ctx,
|
|
Ipmip_proc_t *proc)
|
|
{
|
|
ipmip_netlink_context_stop(ctx, proc);
|
|
ipmip_cli_context_stop(ctx, proc);
|
|
ipmip_timer_context_stop(ctx, proc);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip_context_destroy
|
|
*===========================================================================
|
|
* Description: Destroy the context
|
|
* Parameters: ctx - The context
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL void
|
|
ipmip_context_destroy(Ipmip_context_t *ctx,
|
|
Ipmip_proc_t *proc)
|
|
{
|
|
/**/
|
|
ipmip_log_event_flush(ctx, proc);
|
|
ipcom_mutex_delete(&ctx->log.events_lock);
|
|
|
|
ipmip_cli_context_destroy(ctx, proc);
|
|
|
|
#ifdef IPMIP_USE_INET
|
|
ipmip_dhcp_context_destroy(ctx, proc);
|
|
ipmip_inet_arp_context_destroy(ctx, proc);
|
|
#endif
|
|
|
|
#ifdef IPMIP_USE_INET6
|
|
ipmip_dhcp6_context_destroy(ctx, proc);
|
|
#endif
|
|
|
|
ipmip_netlink_context_destroy(ctx, proc);
|
|
ipmip_pktbuf_context_destroy(ctx, proc);
|
|
|
|
ipmip_timer_context_destroy(ctx, proc);
|
|
|
|
if (ctx->fd_ioctl != IP_INVALID_SOCKET)
|
|
ipcom_socketclose(ctx->fd_ioctl);
|
|
|
|
ipmip_netlink_close(ctx->nl_req);
|
|
ipcom_free(ctx->name);
|
|
ipcom_free(ctx);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip_proc_alloc
|
|
*===========================================================================
|
|
* Description: Create the process context
|
|
* Parameters:
|
|
* Returns: A process context on success
|
|
*
|
|
*/
|
|
IP_GLOBAL Ipmip_proc_t *
|
|
ipmip_proc_alloc(void)
|
|
{
|
|
Ipmip_proc_t *proc = ipcom_calloc(1, sizeof(Ipmip_proc_t));
|
|
if (proc)
|
|
{
|
|
/* Create semaphore */
|
|
ipcom_block_create(&proc->proc_block);
|
|
}
|
|
|
|
return proc;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip_proc_destroy
|
|
*===========================================================================
|
|
* Description: Destroy the process context
|
|
* Parameters: proc - Context
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL void
|
|
ipmip_proc_destroy(Ipmip_proc_t *proc)
|
|
{
|
|
if (proc != IP_NULL)
|
|
{
|
|
ipcom_block_delete(&proc->proc_block);
|
|
ipcom_free(proc);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip_proc_start
|
|
*===========================================================================
|
|
* Description: Start a specific function with the provided arguments.
|
|
* Parameters: ctx - Context
|
|
* proc - The process
|
|
* proc_name - Name of the process
|
|
* func - Thread start function
|
|
* arg - Opaque argument
|
|
* Returns: Thread context, if successful.
|
|
*
|
|
*/
|
|
IP_GLOBAL Ipmip_proc_t *
|
|
ipmip_proc_start(Ipmip_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
const char *proc_name,
|
|
Ipmip_proc_func_t func,
|
|
void *arg)
|
|
{
|
|
Ipmip_proc_t *nproc = ipmip_proc_alloc();
|
|
|
|
IPMIP_UNUSED_PARAMETER(proc);
|
|
if (nproc)
|
|
{
|
|
Ipcom_proc_attr attr;
|
|
Ip_err err;
|
|
|
|
/**/
|
|
ipcom_proc_attr_init(&attr);
|
|
attr.stacksize = IPCOM_PROC_STACK_LARGE;
|
|
|
|
ipcom_snprintf(proc->ntop.ntop_pbuf,
|
|
sizeof(proc->ntop.ntop_pbuf),
|
|
"%s_%s",
|
|
ctx->name,
|
|
proc_name);
|
|
|
|
/* Lock down contexts */
|
|
ipcom_mutex_lock(ipmip_context_proc_lock);
|
|
|
|
/* Setup the start values */
|
|
ipmip_context_thread_arg = arg;
|
|
ipmip_context_thread_proc = nproc;
|
|
ipmip_context_thread_ctx = ctx;
|
|
ipmip_context_thread_func = func;
|
|
|
|
err = ipcom_proc_acreate(proc->ntop.ntop_pbuf, ipmip_proc, &attr, IP_NULL);
|
|
if (err != IPCOM_SUCCESS)
|
|
{
|
|
ipmip_proc_destroy(nproc);
|
|
ipcom_mutex_unlock(ipmip_context_proc_lock);
|
|
return IP_NULL;
|
|
}
|
|
|
|
/* Wait until were signalled */
|
|
ipcom_block_wait(nproc->proc_block, -1);
|
|
ipcom_mutex_unlock(ipmip_context_proc_lock);
|
|
}
|
|
|
|
return nproc;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip_proc_stop
|
|
*===========================================================================
|
|
* Description: Stop a specific thread.
|
|
* Parameters: ctx - Context
|
|
* proc - Thread context
|
|
* stop_proc - Thread context
|
|
* func - Wakeup function
|
|
* arg - Opaque argument
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL void
|
|
ipmip_proc_stop(Ipmip_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
Ipmip_proc_t *stop_proc,
|
|
Ipmip_proc_func_t func,
|
|
void *arg)
|
|
{
|
|
IPMIP_UNUSED_PARAMETER(proc);
|
|
|
|
/* Lock the global mutex */
|
|
ipcom_mutex_lock(ipmip_context_proc_lock);
|
|
|
|
/* Mark it as 'quit' */
|
|
stop_proc->quit = IP_TRUE;
|
|
|
|
/* Trigger the thread */
|
|
if (func != IP_NULL)
|
|
(*func) (ctx, stop_proc, arg);
|
|
|
|
/* Unlock the global lock */
|
|
ipcom_mutex_unlock(ipmip_context_proc_lock);
|
|
|
|
/* Wait for it to report that its fallen out of the loop */
|
|
(void)ipcom_block_wait(stop_proc->proc_block, -1);
|
|
|
|
/**/
|
|
ipmip_proc_destroy(stop_proc);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip_proc_collect
|
|
*===========================================================================
|
|
* Description: See if a particular process has been stopped
|
|
* Parameters: ctx - Context
|
|
* proc - Thread context
|
|
* stop_proc - Thread context
|
|
* Returns: IP_TRUE if the process was collected.
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_bool
|
|
ipmip_proc_collect(Ipmip_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
Ipmip_proc_t *stop_proc)
|
|
{
|
|
Ip_err err;
|
|
|
|
IPMIP_UNUSED_PARAMETER(ctx);
|
|
IPMIP_UNUSED_PARAMETER(proc);
|
|
|
|
ipcom_mutex_lock(ipmip_context_proc_lock);
|
|
|
|
/* Wait for it to report that its fallen out of the loop */
|
|
err = ipcom_block_wait(stop_proc->proc_block, 0);
|
|
|
|
/* Unlock the global lock */
|
|
ipcom_mutex_unlock(ipmip_context_proc_lock);
|
|
|
|
/* If successful; quit */
|
|
if (err == IPCOM_SUCCESS)
|
|
{
|
|
ipmip_proc_destroy(stop_proc);
|
|
return IP_TRUE;
|
|
}
|
|
|
|
return IP_FALSE;
|
|
}
|
|
|
|
IP_GLOBAL Ipmip_context_id_t *
|
|
ipmip_context_id_create(Ip_ptrdiff_t offset,
|
|
Ip_u32 mask)
|
|
{
|
|
Ipmip_context_id_t *idctx = ipcom_calloc(1, sizeof(*idctx));
|
|
|
|
if (idctx == IP_NULL)
|
|
return IP_NULL;
|
|
|
|
idctx->identity_mask = mask;
|
|
idctx->identity_offset = offset;
|
|
idctx->identity_table = ipcom_hash_new((Ipcom_hash_obj_func) ipmip_context_id_hash,
|
|
(Ipcom_hash_key_func) ipmip_context_id_hash,
|
|
(Ipcom_hash_cmp_func) ipmip_context_id_cmp);
|
|
(void)ipcom_mutex_create(&idctx->identity_lock);
|
|
ipcom_block_create(&idctx->identity_empty);
|
|
|
|
/* Start with it available */
|
|
ipcom_block_post(idctx->identity_empty);
|
|
return idctx;
|
|
}
|
|
|
|
IP_GLOBAL void
|
|
ipmip_context_id_destroy(Ipmip_context_id_t *idctx)
|
|
{
|
|
if (idctx != IP_NULL)
|
|
{
|
|
ipcom_mutex_delete(&idctx->identity_lock);
|
|
ipcom_hash_delete(idctx->identity_table);
|
|
ipcom_block_delete(&idctx->identity_empty);
|
|
ipcom_free(idctx);
|
|
}
|
|
}
|
|
|
|
IP_GLOBAL void
|
|
ipmip_context_id_allocate(Ipmip_context_id_t *idctx,
|
|
void *node)
|
|
{
|
|
Ip_u32 *pident = (Ip_u32 *) (((Ip_u8 *)node) + idctx->identity_offset);
|
|
Ip_u32 ident;
|
|
|
|
ipcom_mutex_lock(idctx->identity_lock);
|
|
|
|
for (;;)
|
|
{
|
|
ident = ++idctx->identity;
|
|
ident &= idctx->identity_mask;
|
|
if (ident == 0)
|
|
continue;
|
|
|
|
if (ipcom_hash_get(idctx->identity_table, &ident) == IP_NULL)
|
|
break;
|
|
}
|
|
|
|
*pident = ident;
|
|
ipcom_hash_add(idctx->identity_table, pident);
|
|
|
|
if (idctx->identity_table->elem == 1)
|
|
(void)ipcom_block_wait(idctx->identity_empty, -1);
|
|
|
|
ipcom_mutex_unlock(idctx->identity_lock);
|
|
}
|
|
|
|
|
|
IP_GLOBAL void
|
|
ipmip_context_id_release(Ipmip_context_id_t *idctx,
|
|
void *node)
|
|
{
|
|
Ip_u32 *pident = (Ip_u32 *) (((Ip_u8 *)node) + idctx->identity_offset);
|
|
|
|
if (ipcom_hash_remove(idctx->identity_table, pident) == IPCOM_SUCCESS)
|
|
{
|
|
if (idctx->identity_table->elem == 0)
|
|
ipcom_block_post(idctx->identity_empty);
|
|
}
|
|
}
|
|
|
|
|
|
IP_GLOBAL void *
|
|
ipmip_context_id_get(Ipmip_context_id_t *idctx,
|
|
Ip_u32 ident)
|
|
{
|
|
Ip_u32 *pident;
|
|
pident = ipcom_hash_get(idctx->identity_table, &ident);
|
|
if (pident)
|
|
return (void *)(((Ip_u8*)pident) - idctx->identity_offset);
|
|
|
|
return IP_NULL;
|
|
}
|
|
|
|
IP_GLOBAL Ip_bool
|
|
ipmip_context_id_empty(Ipmip_context_id_t *idctx,
|
|
int wait_timeout)
|
|
{
|
|
if (ipcom_block_wait(idctx->identity_empty, wait_timeout) != IPCOM_SUCCESS)
|
|
return IP_FALSE;
|
|
|
|
ipcom_block_post(idctx->identity_empty);
|
|
return IP_TRUE;
|
|
}
|
|
|
|
IP_GLOBAL void
|
|
ipmip_context_id_foreach(Ipmip_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
Ipmip_context_id_t *idctx,
|
|
Ipmip_util_hash_foreach_t func,
|
|
void *arg1,
|
|
void *arg2)
|
|
{
|
|
struct Ipmip_context_id_hash_cb cbinfo;
|
|
|
|
cbinfo.arg1 = arg1;
|
|
cbinfo.arg2 = arg2;
|
|
cbinfo.func = func;
|
|
|
|
/**/
|
|
ipmip_util_hash_foreach(ctx, proc, idctx->identity_table, (Ipmip_util_hash_foreach_t)ipmip_context_id_foreach_func, idctx, &cbinfo);
|
|
}
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 11 PUBLIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* END OF FILE
|
|
****************************************************************************
|
|
*/
|