1058 lines
29 KiB
C
1058 lines
29 KiB
C
/* iprohc_comp.c - ROHC compressor utility routines */
|
|
|
|
/*
|
|
* Copyright (c) 2008-2013 Wind River Systems, Inc.
|
|
*
|
|
* The right to copy, distribute or otherwise make use of this software
|
|
* may be licensed only pursuant to the terms of an applicable Wind River
|
|
* license agreement. No license to Wind River intellectual property rights
|
|
* is granted herein. All rights not licensed by Wind River are reserved
|
|
* by Wind River.
|
|
*/
|
|
|
|
/*
|
|
modification history
|
|
--------------------
|
|
01s,08aug13,j_y Clean low impact code review defects
|
|
01n,21nov12,ggz Defect WIND00387435. Validate comp/decomp ptrs before usage
|
|
01m,01oct12,ggz Use cid = 1 instead of random val. Defect WIND00380294
|
|
01l,20oct11,ggz Fix for defect WIND00312450
|
|
01k,11feb11,ggz Fix for defect WIND00254208
|
|
01j,10feb11,ggz Resolve a lock issue for non vxworks port. Defet WIND00254463
|
|
01i,13apr10,ggz Resolve 64bit compiler warnings
|
|
01h,24feb09,tlu Replace ipcom_tmo by ipnet_timeout to port to LKM
|
|
01g,15jul08,tlu Add for CID bit map allocation
|
|
01f,03jul08,tlu Modify to call ipcom_random only to init CID
|
|
and release context lock when finding a context
|
|
01e,15jun08,ggz Added normal state to iprohc_comp_state for uncompressed profile
|
|
01d,23jun08,tlu Modify to init CID with a random number
|
|
01c,12may08,tlu Add more debugging functions
|
|
01b,30apr08,tlu Add debug function to print compression context
|
|
01a,07mar08,tlu Created.
|
|
*/
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* DESCRIPTION
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* CONFIGURATION
|
|
****************************************************************************
|
|
*/
|
|
|
|
#include "iprohc_config.h"
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* INCLUDE FILES
|
|
****************************************************************************
|
|
*/
|
|
#define IPCOM_USE_CLIB_PROTO
|
|
|
|
/* ipcom */
|
|
#include <ipcom_type.h>
|
|
#include <ipcom_cstyle.h>
|
|
#include <ipcom_clib.h>
|
|
#include <ipcom_os.h>
|
|
#include <ipcom_sysvar.h>
|
|
#include <ipcom_err.h>
|
|
#include <ipcom_syslog.h>
|
|
#include <ipcom_list.h>
|
|
#include <ipcom_time.h>
|
|
#include <ipcom_inet.h>
|
|
|
|
|
|
/* iprohc */
|
|
#include "iprohc.h"
|
|
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* DEFINES
|
|
****************************************************************************
|
|
*/
|
|
|
|
|
|
IP_EXTERN Iprohc_data iprohc;
|
|
|
|
/* This is a compile flag, turning on it will build debug message into image */
|
|
#undef ROHC_DEBUG
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* LOCAL TYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* LOCAL Data
|
|
****************************************************************************
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* LOCAL PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
IP_STATIC Iprohc_c_context *
|
|
iprohc_c_find_context_by_cid(Iprohc_compressor *comp, Ip_u16 cid,
|
|
Ip_u8 src_addr_type, void *src_addr);
|
|
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* LOCAL FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* iprohc_c_find_context_by_cid
|
|
*===========================================================================
|
|
* Description: Find a compression context according to CID and source
|
|
* address of the feedback pkt.
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Iprohc_c_context *
|
|
iprohc_c_find_context_by_cid(Iprohc_compressor *comp, Ip_u16 cid,
|
|
Ip_u8 src_addr_type, void *src_addr)
|
|
{
|
|
Iprohc_c_context *context, *ncontext;
|
|
#ifdef IPCOM_USE_INET
|
|
Ipa_union *addr4 = IP_NULL;
|
|
#endif
|
|
#ifdef IPCOM_USE_INET6
|
|
struct Ip_in6_addr *addr6 = IP_NULL;
|
|
#endif
|
|
|
|
|
|
#ifdef ROHC_DEBUG
|
|
ipcom_printf("Enter iprohc_c_find_context_by_cid\n");
|
|
#endif
|
|
|
|
|
|
if (src_addr)
|
|
{
|
|
#ifdef IPCOM_USE_INET
|
|
if (src_addr_type == ROHC_PKT_IPV4)
|
|
addr4 = (Ipa_union *)src_addr;
|
|
#ifdef IPCOM_USE_INET6
|
|
else
|
|
#endif /* IPCOM_USE_INET6 */
|
|
#endif
|
|
#ifdef IPCOM_USE_INET6
|
|
if (src_addr_type == ROHC_PKT_IPV6)
|
|
addr6 = (struct Ip_in6_addr *)src_addr;
|
|
#endif
|
|
}
|
|
|
|
IPROHC_COMP_LOCK(comp);
|
|
|
|
for (context = IPCOM_LIST_FIRST(&comp->context_head);
|
|
context != IP_NULL;
|
|
context = ncontext)
|
|
{
|
|
ncontext = IPCOM_LIST_NEXT(&context->context_list);
|
|
|
|
IPROHC_C_CONTEXT_LOCK(context);
|
|
|
|
/* Check the CID */
|
|
if (context->cid == cid)
|
|
{
|
|
/* Check the address if supplied*/
|
|
#ifdef IPCOM_USE_INET
|
|
if (addr4 &&
|
|
(context->stream_type == ROHC_PKT_IPV4) &&
|
|
(addr4->addr32 == context->dst.addr4.addr32))
|
|
goto findit;
|
|
#ifdef IPCOM_USE_INET6
|
|
else
|
|
#endif /* #ifdef IPCOM_USE_INET6 */
|
|
#endif /* #ifdef IPCOM_USE_INET */
|
|
#ifdef IPCOM_USE_INET6
|
|
if (addr6 &&
|
|
(context->stream_type == ROHC_PKT_IPV6) &&
|
|
(ipcom_memcmp(addr6, &context->dst.addr6,
|
|
sizeof(struct Ip_in6_addr)) == 0))
|
|
goto findit;
|
|
#endif /* #ifdef IPCOM_USE_INET6 */
|
|
else
|
|
goto next_c;
|
|
|
|
/* Find the context, return it */
|
|
findit:
|
|
IPROHC_C_CONTEXT_UNLOCK(context);
|
|
IPROHC_COMP_UNLOCK(comp);
|
|
return context;
|
|
}
|
|
|
|
next_c:
|
|
IPROHC_C_CONTEXT_UNLOCK(context);
|
|
}
|
|
IPROHC_COMP_UNLOCK(comp);
|
|
|
|
/* Didn't find the context, return IP_NULL */
|
|
return IP_NULL;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* PUBLIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* iprohc_alloc_compressor
|
|
*===========================================================================
|
|
* Description: Allocate a ROHC compressor structure
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_PUBLIC Iprohc_compressor *
|
|
iprohc_alloc_compressor(struct Iprohc_interface *interface)
|
|
{
|
|
Iprohc_compressor *comp;
|
|
Ip_u32 ra = ipcom_random() & 0x7;
|
|
Ip_u16 cid_map_size;
|
|
|
|
/* Allocate and pre-init compressor structure */
|
|
comp = (Iprohc_compressor *)ipcom_malloc(sizeof(Iprohc_compressor));
|
|
if(comp == IP_NULL)
|
|
return IP_NULL;
|
|
ipcom_memset(comp, 0, sizeof(Iprohc_compressor));
|
|
|
|
/* Allocate CID bit map */
|
|
cid_map_size = (Ip_u16)((iprohc.max_cid+1)/16);
|
|
if ((iprohc.max_cid+1) % 16)
|
|
cid_map_size = (Ip_u16)(cid_map_size + 1);
|
|
comp->bit_map_size = cid_map_size;
|
|
comp->cid_bit_map = ipcom_malloc(2 * cid_map_size);
|
|
if(comp->cid_bit_map == IP_NULL)
|
|
{
|
|
ipcom_free(comp);
|
|
return IP_NULL;
|
|
}
|
|
ipcom_memset(comp->cid_bit_map, 0, (2*cid_map_size));
|
|
/* Mark CID 0 as used in the bit map */
|
|
comp->cid_bit_map[0] |= 1;
|
|
|
|
comp->interface = interface;
|
|
|
|
/* init the next to-be-used CID to a random not 0 value (won't use 0
|
|
* as CID) to avoid confusing of the ADD-CID octet with the PADDING
|
|
* octet */
|
|
comp->to_be_used_cid = (Ip_u16)(ra?ra:1);
|
|
|
|
/* init list */
|
|
ipcom_list_init(&(comp->context_head));
|
|
|
|
#ifdef IPROHC_ENABLE_REENTRANT
|
|
(void)ipcom_mutex_create(&comp->code_mutex);
|
|
#endif
|
|
|
|
return comp;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* iprohc_del_compressor
|
|
*===========================================================================
|
|
* Description: Free a ROHC compressor structure
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_PUBLIC Ip_err
|
|
iprohc_del_compressor(Iprohc_compressor *compressor)
|
|
{
|
|
Ip_err retval = IPCOM_SUCCESS;
|
|
Iprohc_c_context *context, *ncontext;
|
|
|
|
|
|
/* just return IPCOM_SUCCESS for a NULL compressor */
|
|
if (compressor == IP_NULL) return retval;
|
|
|
|
IPROHC_COMP_LOCK(compressor);
|
|
|
|
/* free cid_bit_map */
|
|
ipcom_free(compressor->cid_bit_map);
|
|
|
|
for (context = IPCOM_LIST_FIRST(&compressor->context_head);
|
|
context != IP_NULL;
|
|
context = ncontext)
|
|
{
|
|
ncontext = IPCOM_LIST_NEXT(&context->context_list);
|
|
|
|
compressor->context_num--;
|
|
|
|
/* free the context */
|
|
iprohc.profiles[context->profileid].c_del_context(context);
|
|
}
|
|
IPROHC_COMP_UNLOCK(compressor);
|
|
|
|
#ifdef IPROHC_ENABLE_REENTRANT
|
|
(void)ipcom_mutex_delete(&compressor->code_mutex);
|
|
#endif
|
|
|
|
/* free the compressor */
|
|
ipcom_free(compressor);
|
|
|
|
return retval;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* iprohc_c_del_profile_contexts
|
|
*===========================================================================
|
|
* Description: Free contexts associated with a profile
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_PUBLIC Ip_err
|
|
iprohc_c_del_profile_contexts(Iprohc_compressor *compressor, Ip_u8 profileid)
|
|
{
|
|
Ip_err retval = IPCOM_SUCCESS;
|
|
Iprohc_c_context *context, *ncontext;
|
|
Ip_u16 i, j, m = 0;
|
|
|
|
/* just return IPCOM_SUCCESS for a NULL compressor */
|
|
if (compressor == IP_NULL) return retval;
|
|
|
|
IPROHC_COMP_LOCK(compressor);
|
|
|
|
for (context = IPCOM_LIST_FIRST(&compressor->context_head);
|
|
context != IP_NULL;
|
|
context = ncontext)
|
|
{
|
|
ncontext = IPCOM_LIST_NEXT(&context->context_list);
|
|
if (context->profileid != profileid) continue;
|
|
|
|
compressor->context_num--;
|
|
|
|
/* find the next cid to be allocated */
|
|
i = (Ip_u16)((int)context->cid / 16);
|
|
j = (Ip_u16)((int)context->cid % 16);
|
|
m = (Ip_u16)(1 << j);
|
|
m = (Ip_u16)~m;
|
|
/* Reset CID used flag */
|
|
compressor->cid_bit_map[i] = compressor->cid_bit_map[i] & m;
|
|
|
|
/* free the context */
|
|
iprohc.profiles[context->profileid].c_del_context(context);
|
|
}
|
|
IPROHC_COMP_UNLOCK(compressor);
|
|
|
|
return retval;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* iprohc_comp_mod_cid
|
|
*===========================================================================
|
|
* Description: Allocate a ROHC compressor structure
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_PUBLIC Ip_err
|
|
iprohc_comp_mod_cid(struct Iprohc_interface *interface,
|
|
Ip_u8 profileid, Ip_u16 cid)
|
|
{
|
|
Iprohc_compressor *comp;
|
|
|
|
#ifdef ROHC_DEBUG
|
|
if (((Iprohc_interface *)interface)->have_unitNum)
|
|
{
|
|
ipcom_printf("Enter iprohc_comp_mod_cid, interface %s%d, profileid %d, cid %d\n",
|
|
((Iprohc_interface *)interface)->name,
|
|
((Iprohc_interface *)interface)->unitNum, profileid, cid);
|
|
}
|
|
else
|
|
{
|
|
ipcom_printf("Enter iprohc_comp_mod_cid, interface %s, profileid %d, cid %d\n",
|
|
((Iprohc_interface *)interface)->name, profileid, cid);
|
|
}
|
|
#endif
|
|
|
|
/* Check whether the profile is configured */
|
|
if (iprohc_find_profile(profileid) != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG1(ERR, "iprohc_comp_mod_cid, not a configured profile %d\n",
|
|
profileid);
|
|
return IPCOM_ERR_INVALID_ARG;
|
|
}
|
|
|
|
/* Validate CID value */
|
|
if ((cid < 1) || (cid > iprohc.max_cid))
|
|
{
|
|
IPCOM_LOG2(ERR,
|
|
"iprohc_comp_mod_cid, %d not in valid cid range [1, %d]\n",
|
|
cid, iprohc.max_cid);
|
|
return IPCOM_ERR_INVALID_ARG;
|
|
}
|
|
|
|
comp = ((Iprohc_interface *)interface)->compressor;
|
|
IPROHC_COMP_LOCK(comp);
|
|
|
|
/* init the next to-be-used CID to a random not 0 value (won't use 0
|
|
* as CID) to avoid confusing of the ADD-CID octet with the PADDING
|
|
* octet */
|
|
comp->to_be_used_cid = cid;
|
|
IPROHC_COMP_UNLOCK(comp);
|
|
|
|
#ifdef ROHC_DEBUG
|
|
ipcom_printf("iprohc_comp_mod_cid, modified next to be used cid\n");
|
|
#endif
|
|
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* iprohc_c_context_common_create
|
|
*===========================================================================
|
|
* Description: Allocate a ROHC compression context common structure
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_PUBLIC Iprohc_c_context *
|
|
iprohc_c_context_common_create(Ip_u16 cid)
|
|
{
|
|
Iprohc_c_context *c_context;
|
|
|
|
/* Allocate and pre-init compression context structure */
|
|
c_context = (Iprohc_c_context *)ipcom_malloc(sizeof(Iprohc_c_context));
|
|
if (c_context == IP_NULL)
|
|
{
|
|
IPCOM_LOG0(ERR,"iprohc_c_context_common_create, out of memory");
|
|
return IP_NULL;
|
|
}
|
|
|
|
ipcom_memset(c_context, 0, sizeof(Iprohc_c_context));
|
|
|
|
/* Initialize the context fields */
|
|
c_context->cid = cid;
|
|
c_context->state = ROHC_COMP_STATE_IR;
|
|
c_context->mode = ROHC_MODE_U;
|
|
c_context->pkt_type = ROHC_PKT_IR;
|
|
|
|
#ifdef IPROHC_ENABLE_REENTRANT
|
|
(void)ipcom_mutex_create(&c_context->code_mutex);
|
|
#endif
|
|
|
|
return c_context;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* iprohc_c_context_common_del
|
|
*===========================================================================
|
|
* Description: Free a ROHC compression context common structure
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_PUBLIC Ip_err
|
|
iprohc_c_context_common_del(Iprohc_c_context *c_context)
|
|
{
|
|
|
|
/* Cancel the timer. */
|
|
ipnet_timeout_cancel(c_context->retx_ir);
|
|
|
|
#ifdef IPROHC_ENABLE_REENTRANT
|
|
(void)ipcom_mutex_delete(&c_context->code_mutex);
|
|
#endif
|
|
|
|
ipcom_free(c_context);
|
|
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* iprohc_c_process_feedback
|
|
*===========================================================================
|
|
* Description: Process the received feedback elements from the decompressor
|
|
*
|
|
* Feedback consists of one or more concatenated feedback elements,
|
|
* where each feedback element has the following format:
|
|
*
|
|
* ---------------------------
|
|
* | 1 1 1 1 0 | Code | feedback type octet
|
|
* ---------------------------
|
|
* : Size : if Code = 0
|
|
* ---------------------------
|
|
* / feedback data / variable length
|
|
* ---------------------------
|
|
*
|
|
* The feedback data has the following structure:
|
|
*
|
|
* ---------------------------
|
|
* : Add-CID octet : if for small CIDs and (CID != 0)
|
|
* ---------------------------
|
|
* : :
|
|
* / large CID / 1 - 2 octects for large CIDs
|
|
* : (4.5.6 encoding) :
|
|
* ---------------------------
|
|
* / feedback field /
|
|
* ---------------------------
|
|
*
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_PUBLIC Ip_err
|
|
iprohc_c_process_feedback(Iprohc_compressor *compressor,
|
|
Ip_u8 src_addr_type,
|
|
void *src_addr,
|
|
Ip_u16 feedback_num,
|
|
Ip_u8 *feedbacks)
|
|
{
|
|
Ip_err retval = IPCOM_SUCCESS;
|
|
Ip_u8 pointer = 0, fb_p = 0;
|
|
Ip_u8 size, data_size;
|
|
Ip_u16 cid = 0, i;
|
|
Iprohc_c_context *context;
|
|
|
|
#ifdef ROHC_DEBUG
|
|
ipcom_printf("Enter iprohc_c_process_feedback, feedback_num %d, feedback %x\n",
|
|
feedback_num, feedbacks);
|
|
#endif
|
|
|
|
if (compressor == IP_NULL) goto leave;
|
|
|
|
for (i = 0; i < feedback_num; i++)
|
|
{
|
|
#ifdef ROHC_DEBUG
|
|
ipcom_printf("iprohc_c_process_feedback(for), i %d, pointer %d, feedbacks[pointer] %x\n",
|
|
i, pointer, feedbacks[pointer]);
|
|
#endif
|
|
if ((feedbacks[pointer]>>ROHC_PKT_FEEDBACK_SHIFT) != ROHC_PKT_FEEDBACK)
|
|
{
|
|
/* Pass in a non feedback element */
|
|
IPCOM_LOG0(ERR, "iprohc_c_process_feedback, not a feedback element\n");
|
|
IPROHC_LEAVE(IPCOM_ERR_INVALID_ARG);
|
|
}
|
|
|
|
/* Get the size */
|
|
if ((feedbacks[pointer] & 0x07) == 0)
|
|
{
|
|
/* move the pointer */
|
|
pointer++;
|
|
data_size = size = feedbacks[pointer];
|
|
/* Count Size octet */
|
|
size ++;
|
|
}
|
|
else
|
|
data_size = size = (Ip_u8)(feedbacks[pointer] & 0x07);
|
|
|
|
#ifdef ROHC_DEBUG
|
|
ipcom_printf("iprohc_c_process_feedback, data_size %d, size %d\n",
|
|
data_size, size);
|
|
#endif
|
|
|
|
/* Move the pointer */
|
|
pointer++;
|
|
|
|
/* get the CID */
|
|
if (iprohc.large_cid)
|
|
{
|
|
/*
|
|
* Decode cid according to RFC 3095, 4.5.6.
|
|
* RFC 3095, section 5.2.2: If the first bit is 0, the CID uses
|
|
* one octet. If the first bit is 1, the CID uses two octet.
|
|
*/
|
|
if ((feedbacks[pointer] & 0x80) == 0)
|
|
cid = feedbacks[pointer];
|
|
else
|
|
{
|
|
ipcom_memcpy(&cid, &(feedbacks[pointer]), 2);
|
|
cid = ip_ntohs(cid);
|
|
cid = (Ip_u16)(cid & 0x7fff);
|
|
}
|
|
}
|
|
else if ((feedbacks[pointer]>>ROHC_PKT_ADD_CID_SHIFT)
|
|
== ROHC_PKT_ADD_CID)
|
|
{
|
|
/* Small CID */
|
|
cid = (Ip_u16)(feedbacks[pointer] & 0x0F);
|
|
}
|
|
else
|
|
cid = 0;
|
|
|
|
#ifdef ROHC_DEBUG
|
|
ipcom_printf("iprohc_c_process_feedback, cid %d, size %d\n",
|
|
cid, size);
|
|
#endif
|
|
|
|
/* Find the context according to cid and source address */
|
|
context = iprohc_c_find_context_by_cid(compressor, cid,
|
|
src_addr_type, src_addr);
|
|
|
|
#ifdef ROHC_DEBUG
|
|
if (context)
|
|
{
|
|
ipcom_printf("iprohc_c_process_feedback, find a c_context\n");
|
|
iprohc_c_print_a_context(context);
|
|
}
|
|
else
|
|
ipcom_printf("iprohc_c_process_feedback, didn't find a c_context\n");
|
|
#endif
|
|
|
|
/* Dispatch the feedback field to the compressor context */
|
|
if (context)
|
|
iprohc.profiles[context->profileid].c_process_feedback(context,
|
|
feedbacks+fb_p+size-data_size+1, data_size);
|
|
|
|
/* Move pointer and fb_p to point to the next feedback element */
|
|
fb_p = (Ip_u8)(fb_p + 1 + size);
|
|
pointer = fb_p;
|
|
|
|
#ifdef ROHC_DEBUG
|
|
ipcom_printf("iprohc_c_process_feedback, fb_p %d, pointer %d\n",
|
|
fb_p, pointer);
|
|
#endif
|
|
}
|
|
|
|
leave:
|
|
ipcom_free(feedbacks);
|
|
return retval;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* iprohc_retx_ir_timeout
|
|
*===========================================================================
|
|
* Description: Set next transmitting packet type to be IR if the compression
|
|
* context is not in Pending state.
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_PUBLIC void
|
|
iprohc_retx_ir_timeout(void *cookie)
|
|
{
|
|
Iprohc_c_context *c_context;
|
|
|
|
#ifdef ROHC_DEBUG
|
|
ipcom_printf("iprohc_retx_ir_timeout: retx IR timer times out\n");
|
|
#endif
|
|
|
|
c_context = (Iprohc_c_context *)cookie;
|
|
|
|
IPROHC_C_CONTEXT_LOCK(c_context);
|
|
if (c_context->trans != ROHC_COMP_TRANS_PENDING)
|
|
{
|
|
c_context->pkt_type = ROHC_PKT_IR;
|
|
c_context->ext_type = ROHC_EXT_NO_EXT;
|
|
}
|
|
IPROHC_C_CONTEXT_UNLOCK(c_context);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* iprohc_c_print_a_context
|
|
*===========================================================================
|
|
* Description: For debugging -- print out a compression context
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_PUBLIC void
|
|
iprohc_c_print_a_context(Iprohc_c_context *context)
|
|
{
|
|
Ip_u8 profileid;
|
|
char buf[48], srcbuf[48];
|
|
|
|
profileid = context->profileid;
|
|
|
|
ipcom_printf(" Compression Context (%x):\n", context);
|
|
ipcom_printf(" cid: %d\n", context->cid);
|
|
ipcom_printf(" state: %s\n",
|
|
iprohc_comp_state(context->state));
|
|
ipcom_printf(" mode: %s\n",
|
|
iprohc_context_mode(context->mode));
|
|
ipcom_printf(" decline_mode_trans: %s\n",
|
|
context->decline_mode_trans?"Yes":"No");
|
|
ipcom_printf(" trans: %s\n",
|
|
iprohc_comp_trans(context->trans));
|
|
ipcom_printf(" pkt_type: %s\n",
|
|
iprohc_pkt_type(context->pkt_type));
|
|
ipcom_printf(" ext_type: %s\n",
|
|
iprohc_ext_type(context->ext_type));
|
|
ipcom_printf(" reject: %s\n",
|
|
context->reject?"Yes":"No");
|
|
ipcom_printf(" num_ir: %d\n", context->num_ir);
|
|
ipcom_printf(" num_compressed: %d\n",
|
|
context->num_compressed);
|
|
ipcom_printf(" stream type: %s\n",
|
|
(context->stream_type==ROHC_PKT_IPV4)?"IPv4":"IPv6");
|
|
|
|
if (context->stream_type == ROHC_PKT_IPV4)
|
|
#ifdef IPCOM_USE_INET
|
|
{
|
|
(void)ipcom_inet_ntop(IP_AF_INET, &context->dst.addr4.addr32, buf,
|
|
sizeof(buf));
|
|
(void)ipcom_inet_ntop(IP_AF_INET, &context->src.addr4.addr32, srcbuf,
|
|
sizeof(srcbuf));
|
|
}
|
|
#ifdef IPCOM_USE_INET6
|
|
else
|
|
#endif
|
|
#endif /* #ifdef IPCOM_USE_INET */
|
|
#ifdef IPCOM_USE_INET6
|
|
{
|
|
(void)ipcom_inet_ntop(IP_AF_INET6, &context->dst.addr6, buf,
|
|
sizeof(buf));
|
|
(void)ipcom_inet_ntop(IP_AF_INET6, &context->src.addr6, srcbuf,
|
|
sizeof(srcbuf));
|
|
}
|
|
#endif /* #ifdef IPCOM_USE_INET6 */
|
|
|
|
ipcom_printf(" src address: %s\n", srcbuf);
|
|
ipcom_printf(" dst address: %s\n", buf);
|
|
|
|
/* Print profile specific compression context */
|
|
iprohc.profiles[profileid].c_print_context(context);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* iprohc_c_print_context
|
|
*===========================================================================
|
|
* Description: Print out all the contexts in the compressor
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_PUBLIC Ip_err
|
|
iprohc_c_print_context(Iprohc_compressor *compressor, Ip_u8 profile)
|
|
{
|
|
Ip_err retval = IPCOM_SUCCESS;
|
|
Iprohc_c_context *context, *ncontext;
|
|
|
|
if (compressor == IP_NULL)
|
|
return retval;
|
|
|
|
if (compressor->context_num == 0)
|
|
{
|
|
ipcom_printf(" Compression Context: None\n");
|
|
return retval;
|
|
}
|
|
|
|
for (context = IPCOM_LIST_FIRST(&compressor->context_head);
|
|
context != IP_NULL;
|
|
context = ncontext)
|
|
{
|
|
ncontext = IPCOM_LIST_NEXT(&context->context_list);
|
|
if (context->profileid != profile) continue;
|
|
iprohc_c_print_a_context(context);
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* iprohc_comp_state
|
|
*===========================================================================
|
|
* Description: Debugging utility to print a compression context state
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_PUBLIC char * iprohc_comp_state(Iprohc_comp_state state)
|
|
{
|
|
switch (state)
|
|
{
|
|
case ROHC_COMP_STATE_IR:
|
|
ipcom_strcpy(iprohc.buf, "IR");
|
|
break;
|
|
case ROHC_COMP_STATE_FO:
|
|
ipcom_strcpy(iprohc.buf, "FO");
|
|
break;
|
|
case ROHC_COMP_STATE_SO:
|
|
ipcom_strcpy(iprohc.buf, "SO");
|
|
break;
|
|
case ROHC_COMP_STATE_NORMAL:
|
|
ipcom_strcpy(iprohc.buf, "NORM");
|
|
break;
|
|
default:
|
|
ipcom_strcpy(iprohc.buf, "Illegal");
|
|
break;
|
|
}
|
|
|
|
return iprohc.buf;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* iprohc_comp_trans
|
|
*===========================================================================
|
|
* Description: Debugging utility to print a compression context mode
|
|
* transition state
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_PUBLIC char * iprohc_comp_trans(Iprohc_comp_trans trans)
|
|
{
|
|
switch (trans)
|
|
{
|
|
case ROHC_COMP_TRANS_DONE:
|
|
ipcom_strcpy(iprohc.buf, "Done");
|
|
break;
|
|
case ROHC_COMP_TRANS_PENDING:
|
|
ipcom_strcpy(iprohc.buf, "Pending");
|
|
break;
|
|
default:
|
|
ipcom_strcpy(iprohc.buf, "Illegal");
|
|
break;
|
|
}
|
|
|
|
return iprohc.buf;
|
|
}
|
|
|
|
|
|
|
|
#ifndef IP_PORT_VXWORKS /* for Linux recursive semaphore */
|
|
|
|
/*
|
|
*===========================================================================
|
|
* iprohc_comp_lck
|
|
*===========================================================================
|
|
* Description: This function provides a recursive semaphore lock to an ROHC
|
|
* compressor.
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
|
|
IP_PUBLIC void
|
|
iprohc_comp_lck(Iprohc_compressor *comp)
|
|
{
|
|
Ip_pid_t cpid = ipcom_getpid();
|
|
|
|
#ifdef ROHC_DEBUG
|
|
ipcom_printf("Calling iprohc_comp_lck: pid %d, counter %d, cpid %d\n",
|
|
comp->pid, comp->s_counter, cpid);
|
|
#endif
|
|
|
|
if (comp->pid == 0)
|
|
{
|
|
/* No one has semaphore, take it */
|
|
comp->pid = cpid;
|
|
comp->s_counter = 1;
|
|
ipcom_mutex_lock(comp->code_mutex);
|
|
}
|
|
else if (comp->pid != cpid)
|
|
{
|
|
/* block a different process/task */
|
|
ipcom_mutex_lock(comp->code_mutex);
|
|
comp->pid = cpid;
|
|
comp->s_counter++;
|
|
}
|
|
else
|
|
/* the semaphore is taken by the same process, increase the counter */
|
|
comp->s_counter ++;
|
|
|
|
#ifdef ROHC_DEBUG
|
|
ipcom_printf("iprohc_comp_lck: pid %d, counter %d, cpid %d\n",
|
|
comp->pid, comp->s_counter, cpid);
|
|
#endif
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* iprohc_comp_unlck
|
|
*===========================================================================
|
|
* Description: This function provides a recursive semaphore unlock to an
|
|
* ROHC compressor.
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_PUBLIC void
|
|
iprohc_comp_unlck(Iprohc_compressor *comp)
|
|
{
|
|
Ip_pid_t cpid = ipcom_getpid();
|
|
|
|
#ifdef ROHC_DEBUG
|
|
ipcom_printf("Calling iprohc_comp_unlck: pid %d, counter %d, cpid %d\n",
|
|
comp->pid, comp->s_counter, cpid);
|
|
#endif
|
|
|
|
if (comp->pid != cpid)
|
|
{
|
|
IPCOM_LOG0(ERR, "iprohc_comp_unlck: released by a different process");
|
|
return;
|
|
}
|
|
|
|
/* decrease the counter */
|
|
comp->s_counter --;
|
|
|
|
if (comp->s_counter == 0)
|
|
{
|
|
/* clear the semaphore PID */
|
|
comp->pid = 0;
|
|
|
|
/* release the semaphore */
|
|
ipcom_mutex_unlock(comp->code_mutex);
|
|
}
|
|
#ifdef ROHC_DEBUG
|
|
ipcom_printf("iprohc_comp_unlck: pid %d, counter %d, cpid %d\n",
|
|
comp->pid, comp->s_counter, cpid);
|
|
#endif
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* iprohc_c_context_lck
|
|
*===========================================================================
|
|
* Description: This function provides a recursive semaphore lock to an ROHC
|
|
* compression context.
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
|
|
IP_PUBLIC void
|
|
iprohc_c_context_lck(Iprohc_c_context *context)
|
|
{
|
|
Ip_pid_t cpid = ipcom_getpid();
|
|
|
|
#ifdef ROHC_DEBUG
|
|
ipcom_printf("Calling iprohc_c_context_lck: pid %d, counter %d, cpid %d\n",
|
|
context->pid, context->s_counter, cpid);
|
|
#endif
|
|
|
|
if (context->pid == 0)
|
|
{
|
|
/* No one has semaphore, take it */
|
|
context->pid = cpid;
|
|
context->s_counter = 1;
|
|
ipcom_mutex_lock(context->code_mutex);
|
|
}
|
|
else if (context->pid != cpid)
|
|
{
|
|
/* block a different process/task */
|
|
ipcom_mutex_lock(context->code_mutex);
|
|
context->pid = cpid;
|
|
context->s_counter++;
|
|
}
|
|
else
|
|
/* the semaphore is taken by the same process, increase the counter */
|
|
context->s_counter ++;
|
|
|
|
#ifdef ROHC_DEBUG
|
|
ipcom_printf("iprohc_c_context_lck: pid %d, counter %d, cpid %d\n",
|
|
context->pid, context->s_counter, cpid);
|
|
#endif
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* iprohc_c_context_unlck
|
|
*===========================================================================
|
|
* Description: This function provides a recursive semaphore unlock to an
|
|
* ROHC compression context.
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_PUBLIC void
|
|
iprohc_c_context_unlck(Iprohc_c_context *context)
|
|
{
|
|
Ip_pid_t cpid = ipcom_getpid();
|
|
|
|
#ifdef ROHC_DEBUG
|
|
ipcom_printf("Enter iprohc_c_context_unlck: pid %d, counter %d, cpid %d\n",
|
|
context->pid, context->s_counter, cpid);
|
|
#endif
|
|
|
|
if (context->pid != cpid)
|
|
{
|
|
IPCOM_LOG0(ERR,"iprohc_c_context_unlck: released by different process");
|
|
return;
|
|
}
|
|
|
|
/* decrease the counter */
|
|
context->s_counter --;
|
|
|
|
if (context->s_counter == 0)
|
|
{
|
|
/* clear the semaphore PID */
|
|
context->pid = 0;
|
|
|
|
/* release the semaphore */
|
|
ipcom_mutex_unlock(context->code_mutex);
|
|
}
|
|
#ifdef ROHC_DEBUG
|
|
ipcom_printf("iprohc_c_context_unlck: pid %d, counter %d, cpid %d\n",
|
|
context->pid, context->s_counter, cpid);
|
|
#endif
|
|
}
|
|
|
|
#endif /* !IP_PORT_VXWORKS */
|
|
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* END OF FILE
|
|
****************************************************************************
|
|
*/
|
|
|