555 lines
17 KiB
C
555 lines
17 KiB
C
/* iprohc_decomp.h - ROHC decompressor head file */
|
|
|
|
/*
|
|
* Copyright (c) 2008 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
|
|
--------------------
|
|
01i,05Jul12,ggz Defect WIND00351290. Use ipcom_mutex_lock for unix port
|
|
01h,26aug11,ggz Fix defect WIND00294683. Incorrect ext order in decompressed packet
|
|
01g,12apr10,ggz Resolve 64bit compiler warnings
|
|
01f,20apr09,tlu Fix Linux build warnings for mips64 gcc (cav_ebt5800)
|
|
01e,08jul08,tlu Add to handle IP extension headers
|
|
01d,10jun08,tlu Fix to convert payload length to network format for IPv6
|
|
01c,15may08,tlu Fix the macro to check whether decompression is allowed
|
|
01b,01may08,tlu Add debug function
|
|
01a,06mar08,tlu Created.
|
|
*/
|
|
|
|
#ifndef IPROHC_DECOMP_H
|
|
#define IPROHC_DECOMP_H
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* INCLUDE FILES
|
|
****************************************************************************
|
|
*/
|
|
|
|
#include <ipcom_tags.h>
|
|
#include <ipcom_type.h>
|
|
#include <ipcom_list.h>
|
|
|
|
|
|
#include "iprohc_config.h"
|
|
#include "iprohc_constant.h"
|
|
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* DEFINES
|
|
****************************************************************************
|
|
*/
|
|
|
|
#define IPROHC_ENABLE_REENTRANT
|
|
|
|
|
|
#ifdef IPROHC_ENABLE_REENTRANT
|
|
|
|
#if defined(IP_PORT_VXWORKS) || defined(IP_PORT_UNIX)
|
|
|
|
#define IPROHC_DECOMP_LOCK(decomp) ipcom_mutex_lock((decomp)->code_mutex)
|
|
#define IPROHC_DECOMP_UNLOCK(decomp) ipcom_mutex_unlock((decomp)->code_mutex)
|
|
|
|
#define IPROHC_D_CONTEXT_LOCK(context) ipcom_mutex_lock((context)->code_mutex)
|
|
#define IPROHC_D_CONTEXT_UNLOCK(context) ipcom_mutex_unlock((context)->code_mutex)
|
|
|
|
#else /* !IP_PORT_VXWORKS, Linux recursive semaphore */
|
|
|
|
#define IPROHC_DECOMP_LOCK(decomp) iprohc_decomp_lck(decomp)
|
|
#define IPROHC_DECOMP_UNLOCK(decomp) iprohc_decomp_unlck(decomp)
|
|
|
|
#define IPROHC_D_CONTEXT_LOCK(context) iprohc_d_context_lck(context)
|
|
#define IPROHC_D_CONTEXT_UNLOCK(context) iprohc_d_context_unlck(context)
|
|
|
|
#endif /* IP_PORT_VXWORKS */
|
|
|
|
#else
|
|
|
|
#define IPROHC_DECOMP_LOCK(comp) IP_NOOP
|
|
#define IPROHC_DECOMP_UNLOCK(comp) IP_NOOP
|
|
|
|
#define IPROHC_D_CONTEXT_LOCK(context) IP_NOOP
|
|
#define IPROHC_D_CONTEXT_UNLOCK(context) IP_NOOP
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* IPROHC_DECOMP_ALLOWED
|
|
*===========================================================================
|
|
* Check whether decompression is allowed according to RFC 3095, 5.3.2.2.1:
|
|
* In Full context state, allow to decompress any type of packets;
|
|
* In Static context state, only IR, IR-DYN, and UOR-2 packets are allowed;
|
|
* In No context state, only IR packets are allowed.
|
|
*/
|
|
#define IPROHC_DECOMP_ALLOWED(context, pkt_type, sn) \
|
|
{ \
|
|
Iprohc_feedback *feedback = IP_NULL; \
|
|
\
|
|
if (context->state == ROHC_DECOMP_STATE_NO) \
|
|
{ \
|
|
if (pkt_type != ROHC_PKT_IR) \
|
|
{ \
|
|
/* Send STATIC-NACK feedback */ \
|
|
feedback = iprohc_create_feedback_2(context, \
|
|
ROHC_FEEDBACK_STATIC_NACK, sn); \
|
|
} \
|
|
} \
|
|
else if (context->state == ROHC_DECOMP_STATE_STATIC) \
|
|
{ \
|
|
if ((pkt_type != ROHC_PKT_IR) && \
|
|
(pkt_type != ROHC_PKT_IR_DYN) && \
|
|
(pkt_type != ROHC_PKT_TYPE_2)) \
|
|
{ \
|
|
/* Send NACK feedback */ \
|
|
feedback = iprohc_create_feedback_2(context, \
|
|
ROHC_FEEDBACK_NACK, sn); \
|
|
} \
|
|
} \
|
|
\
|
|
if (feedback != IP_NULL) \
|
|
{ \
|
|
if (context->trans == ROHC_DECOMP_TRANS_INITIATED) \
|
|
/* Feedback pkts that initiate the mode transition must */ \
|
|
/* carry CRC option */ \
|
|
iprohc_feedback_add_option(feedback, ROHC_FEEDBACK_OPT_CRC, 1, 0); \
|
|
\
|
|
IPROHC_ERROUT(IPCOM_ERR_PERMISSION_DENIED); \
|
|
} \
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* IPROHC_RECONSTRUCT_IP_EXT
|
|
*===========================================================================
|
|
* Re-construct an IP extension header from the decompressor context:
|
|
* - Loop through the reference list to re-construct IP extension headers
|
|
*/
|
|
#define IPROHC_RECONSTRUCT_IP_EXT(iprohc_header, pkt) \
|
|
{ \
|
|
Iprohc_ref_list *ext_hdr, *n_ext_hdr; \
|
|
\
|
|
for (ext_hdr = IPCOM_LIST_LAST(&iprohc_header->ref_head); \
|
|
ext_hdr; \
|
|
ext_hdr = n_ext_hdr) \
|
|
{ \
|
|
n_ext_hdr = IPCOM_LIST_PREV(&ext_hdr->ref_list); \
|
|
/* move pointer back for the extension header */ \
|
|
pkt->ipstart -= ext_hdr->length; \
|
|
pkt->start = pkt->ipstart; \
|
|
/* copy the extension header to the packet */ \
|
|
ipcom_memcpy(&(pkt->data[pkt->ipstart]), ext_hdr->data, \
|
|
ext_hdr->length); \
|
|
} \
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* IPROHC_RECONSTRUCT_IPV4
|
|
*===========================================================================
|
|
* Re-construct an IP header from the decompressor context:
|
|
* - Calculate datagram length from ipstart/start and end pointers.
|
|
* - Calculate header checksum.
|
|
* - Move the ipstart and start pointers
|
|
* - Copy the IP header to the packet
|
|
*/
|
|
#ifdef IPCOM_USE_INET
|
|
#define IPROHC_RECONSTRUCT_IPV4(iprohc_header, pkt) \
|
|
{ \
|
|
if (iprohc_header->has_exten) \
|
|
{ \
|
|
/* Re-construct IP extenstion headers */ \
|
|
IPROHC_RECONSTRUCT_IP_EXT(iprohc_header, pkt); \
|
|
} \
|
|
\
|
|
/* IHL = 5, 20 octets */ \
|
|
pkt->ipstart -= IPROHC_IP4_HDR_SIZE; \
|
|
pkt->start = pkt->ipstart; \
|
|
iprohc_header->header.ip4.length = ip_htons(pkt->end - pkt->start); \
|
|
\
|
|
/* Reset checksum to 0 to calculate header checksum */ \
|
|
iprohc_header->header.ip4.checksum = 0; \
|
|
iprohc_header->header.ip4.checksum = \
|
|
ipcom_in_checksum(&iprohc_header->header.ip4, \
|
|
(Ip_size_t)((iprohc_header->header.ip4.vers_len & 0x0F)*4)); \
|
|
ipcom_memcpy(&(pkt->data[pkt->ipstart]), &(iprohc_header->header.ip4), \
|
|
IPROHC_IP4_HDR_SIZE); \
|
|
}
|
|
#else
|
|
#define IPROHC_RECONSTRUCT_IPV4(iprohc_header, pkt) IP_NOOP
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* IPROHC_RECONSTRUCT_IPV6
|
|
*===========================================================================
|
|
* Re-construct an IPv6 header from the decompressor context:
|
|
* - Calculate payload length from ipstart/start and end pointers.
|
|
* - Move the ipstart and start pointers
|
|
* - Copy the IPv6 header to the packet
|
|
*/
|
|
#ifdef IPCOM_USE_INET6
|
|
#define IPROHC_RECONSTRUCT_IPV6(iprohc_header, pkt) \
|
|
{ \
|
|
if (iprohc_header->has_exten) \
|
|
{ \
|
|
/* Re-construct IP extenstion headers */ \
|
|
IPROHC_RECONSTRUCT_IP_EXT(iprohc_header, pkt); \
|
|
} \
|
|
\
|
|
iprohc_header->header.ip6.plen = ip_htons(pkt->end - pkt->start); \
|
|
/* IPv6 header length = 40 octets */ \
|
|
pkt->ipstart -= IPROHC_IP6_HDR_SIZE; \
|
|
pkt->start = pkt->ipstart; \
|
|
ipcom_memcpy(&pkt->data[pkt->ipstart], &(iprohc_header->header.ip6), \
|
|
IPROHC_IP6_HDR_SIZE); \
|
|
}
|
|
#else
|
|
#define IPROHC_RECONSTRUCT_IPV6(iprohc_header, pkt) IP_NOOP
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* IPROHC_RECONSTRUCT_IP
|
|
*===========================================================================
|
|
* Re-construct IP headers from the context
|
|
*/
|
|
#define IPROHC_RECONSTRUCT_IP(ip_context, pkt) \
|
|
{ \
|
|
Iprohc_ip_header *ip_header, *p_ip_header; \
|
|
\
|
|
for (ip_header = IPCOM_LIST_LAST(&ip_context->ip_head); \
|
|
ip_header; \
|
|
ip_header = p_ip_header) \
|
|
{ \
|
|
p_ip_header = IPCOM_LIST_PREV(&ip_header->ip_list); \
|
|
\
|
|
if (ip_header->packet_type == ROHC_PKT_IPV4) \
|
|
{ \
|
|
/* Re-construct an IPv4 header */ \
|
|
IPROHC_RECONSTRUCT_IPV4(ip_header, pkt); \
|
|
} \
|
|
else \
|
|
{ \
|
|
/* Re-construct an IPv6 header */ \
|
|
IPROHC_RECONSTRUCT_IPV6(ip_header, pkt); \
|
|
} \
|
|
} \
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* IPROHC_D_F_STATE_TRANS
|
|
*===========================================================================
|
|
* Process state transition at decompressor when a decompression fails
|
|
*/
|
|
#define IPROHC_D_F_STATE_TRANS(d_context, sn) \
|
|
{ \
|
|
Ip_u8 ratio; \
|
|
Iprohc_feedback *feedback_v = IP_NULL; \
|
|
\
|
|
/* Calculate the failure ratio */ \
|
|
ratio = (Ip_u8)((d_context->num_decompressed * 100) % d_context->num_failed); \
|
|
\
|
|
/* State transits to Static/No Context: RFC 3095, 5.3.2.1 */ \
|
|
if (d_context->state == ROHC_DECOMP_STATE_FULL) \
|
|
{ \
|
|
if (ratio >= IPROHC_D_FULL_RATIO) \
|
|
{ \
|
|
d_context->state = ROHC_DECOMP_STATE_STATIC; \
|
|
\
|
|
/* Send NACK */ \
|
|
feedback_v = iprohc_create_feedback_2(d_context, \
|
|
ROHC_FEEDBACK_NACK, sn); \
|
|
} \
|
|
} \
|
|
else if (d_context->state == ROHC_DECOMP_STATE_STATIC) \
|
|
{ \
|
|
if (ratio >= IPROHC_D_STATIC_RATIO) \
|
|
{ \
|
|
d_context->state = ROHC_DECOMP_STATE_NO; \
|
|
\
|
|
/* Send NACK */ \
|
|
feedback_v = iprohc_create_feedback_2(d_context, \
|
|
ROHC_FEEDBACK_NACK, sn); \
|
|
} \
|
|
} \
|
|
\
|
|
if ((feedback_v != IP_NULL) && \
|
|
(context->trans == ROHC_DECOMP_TRANS_INITIATED)) \
|
|
{ \
|
|
/* Feedback pkts that initiate the mode transition must */ \
|
|
/* carry CRC option */ \
|
|
iprohc_feedback_add_option(feedback_v, ROHC_FEEDBACK_OPT_CRC, 1, 0); \
|
|
} \
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* IPROHC_D_MODE_TRANS
|
|
*===========================================================================
|
|
* Process mode transition at decompressor
|
|
*/
|
|
#define IPROHC_D_MODE_TRANS(d_context, mode) \
|
|
{ \
|
|
if (mode == ROHC_MODE_C) \
|
|
{ \
|
|
/* mode transition request is declined at compressor, */ \
|
|
/* -- reset trans mode back to mode, and set trans as Pending */ \
|
|
d_context->trans_mode = d_context->mode; \
|
|
d_context->trans = ROHC_DECOMP_TRANS_PENDING; \
|
|
} \
|
|
else if ((d_context->mode == ROHC_MODE_U) && \
|
|
(d_context->trans == ROHC_DECOMP_TRANS_DONE)) \
|
|
{ \
|
|
/* Initiate the mode transition: U-mode-->O-mode */ \
|
|
d_context->trans_mode = ROHC_MODE_O; \
|
|
d_context->trans = ROHC_DECOMP_TRANS_INITIATED; \
|
|
} \
|
|
else if (mode == (int)d_context->trans_mode) \
|
|
{ \
|
|
/* mode transition request is accepted at compressor, */ \
|
|
/* -- set trans and mode */ \
|
|
if (d_context->trans == ROHC_DECOMP_TRANS_INITIATED) \
|
|
{ \
|
|
d_context->mode = d_context->trans_mode; \
|
|
d_context->trans = ROHC_DECOMP_TRANS_PENDING; \
|
|
} \
|
|
else if (d_context->trans == ROHC_DECOMP_TRANS_PENDING) \
|
|
d_context->trans = ROHC_DECOMP_TRANS_DONE; \
|
|
} \
|
|
else if ((mode == -1) && (d_context->trans == ROHC_DECOMP_TRANS_PENDING))\
|
|
{ \
|
|
d_context->trans = ROHC_DECOMP_TRANS_DONE; \
|
|
} \
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* Deompressor states
|
|
*===========================================================================
|
|
* refer to RFC 3095, section 4.3.2
|
|
*/
|
|
|
|
typedef enum
|
|
{
|
|
ROHC_DECOMP_STATE_NO = 1,
|
|
ROHC_DECOMP_STATE_STATIC,
|
|
ROHC_DECOMP_STATE_FULL
|
|
} Iprohc_decomp_state;
|
|
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* De-compressor mode transitions
|
|
*===========================================================================
|
|
* refer to RFC 3095, section 5.6.1
|
|
*/
|
|
|
|
typedef enum
|
|
{
|
|
ROHC_DECOMP_TRANS_DONE = 0,
|
|
ROHC_DECOMP_TRANS_INITIATED,
|
|
ROHC_DECOMP_TRANS_PENDING
|
|
} Iprohc_decomp_trans;
|
|
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* Public TYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* LOCAL TYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
struct Iprohc_decompressor;
|
|
struct Iprohc_interface;
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* Iprohc_d_context
|
|
*===========================================================================
|
|
* This is the ROHC decompression context structure
|
|
*/
|
|
|
|
typedef struct Iprohc_d_context_struct
|
|
{
|
|
Ipcom_list context_list;
|
|
|
|
/* CID allocated for the context */
|
|
Ip_u16 cid;
|
|
|
|
/* decompression state */
|
|
Iprohc_decomp_state state;
|
|
|
|
/* decompression mode */
|
|
Iprohc_mode mode;
|
|
|
|
/* decompression mode transition */
|
|
Iprohc_decomp_trans trans;
|
|
|
|
/* decompression mode to be transited to */
|
|
Iprohc_mode trans_mode;
|
|
|
|
/* first IR received for context, parsed during creating the context */
|
|
Ip_bool first_ir;
|
|
|
|
/* number of successfully decompressed packets */
|
|
Ip_u32 num_decompressed;
|
|
|
|
/* number of failed decompressed packets */
|
|
Ip_u32 num_failed;
|
|
|
|
/* stream type: IPv4 or IPv6, for feedback processing */
|
|
Ip_u8 stream_type;
|
|
|
|
/* source address of the stream, for feedback processing */
|
|
Iprohc_addr src;
|
|
|
|
/* destination address of the stream, for feedback processing */
|
|
Iprohc_addr dst;
|
|
|
|
/* profile the context is associated with */
|
|
Ip_u8 profileid;
|
|
|
|
/* Compressor the context is associated with */
|
|
struct Iprohc_decompressor *decompressor;
|
|
|
|
/* CRC used to validate the packet */
|
|
Ip_u8 crc;
|
|
|
|
#ifdef IPROHC_ENABLE_REENTRANT
|
|
Ipcom_mutex code_mutex; /* Mutex to protect compressor data. */
|
|
#endif
|
|
|
|
#ifndef IP_PORT_VXWORKS /* for Linux recursive semaphore */
|
|
/* the process that currently holds the semaphore and taken counter */
|
|
Ip_pid_t pid;
|
|
Ip_u8 s_counter;
|
|
#endif /* !IP_PORT_VXWORKS */
|
|
|
|
/* profile specific decompression context structure */
|
|
void *profile_context;
|
|
}
|
|
Iprohc_d_context;
|
|
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* Iprohc_decompressor
|
|
*===========================================================================
|
|
* This is the ROHC decompressor context structure
|
|
*/
|
|
|
|
typedef struct Iprohc_decompressor_struct
|
|
{
|
|
|
|
/* Context list */
|
|
Ip_u16 context_num; /* number of contexts */
|
|
Ipcom_list context_head;
|
|
|
|
/* interface the decompressor is associated with */
|
|
struct Iprohc_interface *interface;
|
|
|
|
#ifdef IPROHC_ENABLE_REENTRANT
|
|
Ipcom_mutex code_mutex; /* Mutex to protect compressor data. */
|
|
#endif
|
|
|
|
#ifndef IP_PORT_VXWORKS /* for Linux recursive semaphore */
|
|
/* the process that currently holds the semaphore and taken counter */
|
|
Ip_pid_t pid;
|
|
Ip_u8 s_counter;
|
|
#endif /* !IP_PORT_VXWORKS */
|
|
}
|
|
Iprohc_decompressor;
|
|
|
|
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* GLOBAL FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
IP_PUBLIC Iprohc_decompressor * iprohc_alloc_decompressor(struct Iprohc_interface *interface);
|
|
IP_PUBLIC Ip_err iprohc_del_decompressor(Iprohc_decompressor *decompressor);
|
|
IP_PUBLIC Ip_err iprohc_d_del_profile_contexts(Iprohc_decompressor *decompressor, Ip_u8 profileid);
|
|
|
|
IP_PUBLIC Iprohc_d_context * iprohc_d_context_common_create(Ip_u16 cid);
|
|
IP_PUBLIC Ip_err iprohc_d_context_common_del(Iprohc_d_context *d_context);
|
|
IP_PUBLIC Ip_err iprohc_d_print_context(Iprohc_decompressor *decompressor, Ip_u8 profile);
|
|
|
|
/* Debug functions */
|
|
IP_PUBLIC void iprohc_d_print_a_context(Iprohc_d_context *context);
|
|
IP_PUBLIC char * iprohc_decomp_state(Iprohc_decomp_state state);
|
|
IP_PUBLIC char * iprohc_decomp_trans(Iprohc_decomp_trans trans);
|
|
|
|
|
|
#ifndef IP_PORT_VXWORKS /* for Linux recursive semaphore */
|
|
|
|
IP_PUBLIC void iprohc_decomp_lck(Iprohc_decompressor *decomp);
|
|
IP_PUBLIC void iprohc_decomp_unlck(Iprohc_decompressor *decomp);
|
|
|
|
IP_PUBLIC void iprohc_d_context_lck(Iprohc_d_context *context);
|
|
IP_PUBLIC void iprohc_d_context_unlck(Iprohc_d_context *context);
|
|
|
|
#endif /* !IP_PORT_VXWORKS */
|
|
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
#endif /* #ifndef IPROHC_DECOMP_H */
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* END OF FILE
|
|
****************************************************************************
|
|
*/
|
|
|