Files
2026-07-30 11:19:44 +05:30

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
****************************************************************************
*/