437 lines
14 KiB
C
437 lines
14 KiB
C
/* iprohc_format.h - ROHC formatting 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,20mar12,ggz Fix WIND00340441
|
|
01h,25aug11,ggz Fix WIND00290718
|
|
01g,09apr10,ggz Fix 64bit compiler warnings
|
|
01f,20apr09,tlu Fix Linux build warnings for mips64 gcc (cav_ebt5800)
|
|
01e,26sep08,tlu Initialize buff[4] in IPv4 dynamic format macro to 0
|
|
01d,03jul08,tlu Add to handle IP extension headers
|
|
01c,21may08,tlu Use encoded SN to format base header
|
|
01b,20may08,tlu Add large CID encoding macro
|
|
01a,25mar08,tlu Created.
|
|
*/
|
|
|
|
#ifndef IPROHC_FORMAT_H
|
|
#define IPROHC_FORMAT_H
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* INCLUDE FILES
|
|
****************************************************************************
|
|
*/
|
|
|
|
#include <ipcom_type.h>
|
|
#include <ipcom_clib.h>
|
|
#include <ipcom_inet.h>
|
|
#include <ipcom_cstyle.h>
|
|
|
|
|
|
#include "iprohc_constant.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/*
|
|
****************************************************************************
|
|
* DEFINES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*===========================================================================
|
|
* IPROHC_FMT_LIST_ET0
|
|
*===========================================================================
|
|
* Add the compressed list encoding type 0
|
|
*
|
|
* 5.8.6.1 Encoding Type 0 (generic scheme)
|
|
*
|
|
* ---------------------------------
|
|
* | ET=0 |GP|PS| CC = m |
|
|
* ---------------------------------
|
|
* : gen_id : 1 octet, if GP = 1
|
|
* ---------------------------------
|
|
* | XI 1, ..., XI m | m octets, or m * 4 bits
|
|
* / -----------------/
|
|
* | : Padding : if PS = 0 and m is odd
|
|
* ---------------------------------
|
|
* / item1, ..., item n / variable
|
|
* ---------------------------------
|
|
*
|
|
*/
|
|
#define IPROHC_FMT_LIST_ET0(iprohc_header, edata) \
|
|
{ \
|
|
int i; \
|
|
Iprohc_ref_list *ext_hdr, *n_ext_hdr; \
|
|
Ip_u8 *ebuff = (Ip_u8 *)edata; \
|
|
\
|
|
ebuff[0] = iprohc_header->ref_num; \
|
|
ebuff[1] = iprohc_header->gen_id; \
|
|
\
|
|
if (iprohc_header->ref_num < 8) \
|
|
{ \
|
|
ebuff[0] |= 0x20; \
|
|
for (i = 1; i <= iprohc_header->ref_num/2; i++) \
|
|
{ \
|
|
ebuff[i+1] = (Ip_u8)(0x88 | (i<<4)); \
|
|
ebuff[i+1] |= (Ip_u8)(i+1); \
|
|
} \
|
|
if (iprohc_header->ref_num % 2) \
|
|
{ \
|
|
ebuff[i+1] = (Ip_u8)(0x80 | (i<<4)); \
|
|
i++; /* point to next byte to be formatted */ \
|
|
} \
|
|
} \
|
|
else \
|
|
{ \
|
|
ebuff[0] |= 0x30; \
|
|
for (i=1; i <= iprohc_header->ref_num; i++) \
|
|
ebuff[i+1] = (Ip_u8)(0x80 | i); \
|
|
} \
|
|
\
|
|
for (ext_hdr = IPCOM_LIST_FIRST(&iprohc_header->ref_head); \
|
|
ext_hdr; \
|
|
ext_hdr = n_ext_hdr) \
|
|
{ \
|
|
n_ext_hdr = IPCOM_LIST_NEXT(&ext_hdr->ref_list); \
|
|
ipcom_memcpy(&ebuff[i+1], ext_hdr->data, ext_hdr->length); \
|
|
i += ext_hdr->length; \
|
|
} \
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* IPROHC_FMT_IPV4_STATIC
|
|
*===========================================================================
|
|
* Add an IPv4 static part to Static chain in a IR packet
|
|
*
|
|
* 5.7.7.4 IPv4 header static part format
|
|
*
|
|
* ---------------------------------
|
|
* | version = 4 | 0 |
|
|
* ---------------------------------
|
|
* | Protocol |
|
|
* ---------------------------------
|
|
* / Source Address / 4 octets
|
|
* ---------------------------------
|
|
* / Destination Address / 4 octets
|
|
* ---------------------------------
|
|
*
|
|
*/
|
|
#ifdef IPCOM_USE_INET
|
|
#define IPROHC_FMT_IPV4_STATIC(iprohc_header, data) \
|
|
{ \
|
|
Ipcom_ip_header *ip4_header = &(iprohc_header->header.ip4); \
|
|
Ip_u8 *buff = (Ip_u8 *)data; \
|
|
\
|
|
buff[0] = 0x40; \
|
|
buff[1] = ip4_header->protocol; \
|
|
ipcom_memcpy(&buff[2], &ip4_header->src, 4); \
|
|
ipcom_memcpy(&buff[6], &ip4_header->dst, 4); \
|
|
}
|
|
#else
|
|
#define IPROHC_FMT_IPV4_STATIC(iprohc_header, data) IP_NOOP
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* IPROHC_FMT_IPV6_STATIC
|
|
*===========================================================================
|
|
* Add an IPv6 static part to Static chain in a IR packet
|
|
*
|
|
* 5.7.7.3 IPv6 header static part format
|
|
*
|
|
* ---------------------------------
|
|
* | version = 6 |Flow Label (msb) | 1 octet
|
|
* ---------------------------------
|
|
* | Flow Label (lsb) | 2 octets
|
|
* ---------------------------------
|
|
* | Next Header | 1 octet
|
|
* ---------------------------------
|
|
* / Source Address / 16 octets
|
|
* ---------------------------------
|
|
* / Destination Address / 16 octets
|
|
* ---------------------------------
|
|
*
|
|
*/
|
|
#ifdef IPCOM_USE_INET6
|
|
#define IPROHC_FMT_IPV6_STATIC(iprohc_header, data) \
|
|
{ \
|
|
Ipcom_ip6_header *ip6_header = &(iprohc_header->header.ip6); \
|
|
Ip_u32 flow; \
|
|
Ip_u16 flow_lsb; \
|
|
Ip_u8 *buff = (Ip_u8 *)data; \
|
|
\
|
|
buff[0] = 0x60; \
|
|
flow = IP_GET_NTOHL(&ip6_header->ver_class_flow) & 0xfffff; \
|
|
flow_lsb = (Ip_u16)(flow & 0xffff); \
|
|
buff[0] = (Ip_u8)(buff[0] | ((flow >> 16) & 0x0f)); \
|
|
flow_lsb = ip_htons(flow_lsb); \
|
|
ipcom_memcpy(&buff[1], &flow_lsb, 2); \
|
|
buff[3] = ip6_header->nxt; \
|
|
ipcom_memcpy(&buff[4], &ip6_header->src, 16); \
|
|
ipcom_memcpy(&buff[20], &ip6_header->dst, 16); \
|
|
}
|
|
#else
|
|
#define IPROHC_FMT_IPV6_STATIC(iprohc_header, data) IP_NOOP
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* IPROHC_FMT_IPV4_DYNAMIC
|
|
*===========================================================================
|
|
* Add an IPv4 dynamic part to Dynamic chain in a IR/IR-DYN packet
|
|
*
|
|
* 5.7.7.4 IPv4 header dynamic part format
|
|
*
|
|
* ---------------------------------
|
|
* | Type of Service |
|
|
* ---------------------------------
|
|
* | Time to Live |
|
|
* ---------------------------------
|
|
* / Identification / 2 octets
|
|
* ---------------------------------
|
|
* | DF|RND|NBO|SID| 0 |
|
|
* ---------------------------------
|
|
* / Generic extension Header list / (not supported)
|
|
* ---------------------------------
|
|
*
|
|
*/
|
|
#ifdef IPCOM_USE_INET
|
|
#define IPROHC_FMT_IPV4_DYNAMIC(iprohc_header, data) \
|
|
{ \
|
|
Ipcom_ip_header *ip4_header = &(iprohc_header->header.ip4); \
|
|
Ip_u8 *buff = (Ip_u8 *)data; \
|
|
\
|
|
buff[0] = ip4_header->tos; \
|
|
buff[1] = ip4_header->ttl; \
|
|
ipcom_memcpy(&buff[2], &(ip4_header->id), 2); \
|
|
buff[4] = 0x00; \
|
|
if (ip4_header->frag & IPCOM_IPFRAG_DF) buff[4] = 0x80; \
|
|
if (iprohc_header->rnd) buff[4] |= 0x40; \
|
|
if (iprohc_header->nbo) buff[4] |= 0x20; \
|
|
if (iprohc_header->sid) buff[4] |= 0x10; \
|
|
if (iprohc_header->has_exten) \
|
|
IPROHC_FMT_LIST_ET0(iprohc_header, &buff[5]); \
|
|
}
|
|
#else
|
|
#define IPROHC_FMT_IPV4_DYNAMIC(iprohc_header, data) IP_NOOP
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* IPROHC_FMT_IPV6_DYNAMIC
|
|
*===========================================================================
|
|
* Add an IPv6 dynamic part to Dynamic chain in a IR/IR-DYN packet
|
|
*
|
|
* 5.7.7.3 IPv6 header dynamic part format
|
|
*
|
|
* ---------------------------------
|
|
* | Traffic Class | 1 octet
|
|
* ---------------------------------
|
|
* | Hop Limit | 1 octet
|
|
* ---------------------------------
|
|
* / Generic extension Header list / (not supported)
|
|
* ---------------------------------
|
|
*
|
|
*/
|
|
#ifdef IPCOM_USE_INET6
|
|
#define IPROHC_FMT_IPV6_DYNAMIC(iprohc_header, data) \
|
|
{ \
|
|
Ipcom_ip6_header *ip6_header; \
|
|
Ip_u8 *buff = (Ip_u8 *)data; \
|
|
\
|
|
ip6_header = (Ipcom_ip6_header *)&(iprohc_header->header.ip6); \
|
|
buff[0] = (Ip_u8)((IP_GET_NTOHL(&ip6_header->ver_class_flow)>>20)&0xff); \
|
|
buff[1] = ip6_header->hlim; \
|
|
if (iprohc_header->has_exten) \
|
|
IPROHC_FMT_LIST_ET0(iprohc_header, &buff[2]); \
|
|
}
|
|
#else
|
|
#define IPROHC_FMT_IPV6_DYNAMIC(iprohc_header, data) IP_NOOP
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* IPROHC_FMT_IP_STATIC
|
|
*===========================================================================
|
|
* Fomat Static chain in a IR packet
|
|
*/
|
|
#define IPROHC_FMT_IP_STATIC(ip_context, pointer, 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) \
|
|
{ \
|
|
/* Move pointer back for one IPv4 static part */ \
|
|
pointer -= 10; \
|
|
\
|
|
/* Add an IPv4 static part to Static chain */ \
|
|
IPROHC_FMT_IPV4_STATIC(ip_header, &pkt->data[pointer]); \
|
|
} \
|
|
else \
|
|
{ \
|
|
/* Move pointer back for one IPv6 static part */ \
|
|
pointer -= 36; \
|
|
\
|
|
/* Add an IPv6 static part to static chain */ \
|
|
IPROHC_FMT_IPV6_STATIC(ip_header, &pkt->data[pointer]); \
|
|
} \
|
|
} \
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* IPROHC_FMT_IP_DYNAMIC
|
|
*===========================================================================
|
|
* Fomat Dynamic chain in a IR/IR-DYN packet
|
|
*/
|
|
#define IPROHC_FMT_IP_DYNAMC(ip_context, pointer, pkt, has_dynamic, num_h) \
|
|
{ \
|
|
Iprohc_ip_header *ip_header, *p_ip_header; \
|
|
Ip_u8 et0_len; \
|
|
\
|
|
for (ip_header = IPCOM_LIST_LAST(&ip_context->ip_head); \
|
|
(ip_header && num_h); \
|
|
ip_header = p_ip_header, num_h--) \
|
|
{ \
|
|
p_ip_header = IPCOM_LIST_PREV(&ip_header->ip_list); \
|
|
has_dynamic = IP_TRUE; \
|
|
et0_len = 0; \
|
|
\
|
|
/* Calculate compressed list ET0 header length */ \
|
|
if (ip_header->ref_num != 0) \
|
|
{ \
|
|
if (ip_header->ref_num < 8) \
|
|
et0_len = (Ip_u8)(2 + (ip_header->ref_num/2) + (ip_header->ref_num%2)); \
|
|
else \
|
|
et0_len = (Ip_u8)(2 + ip_header->ref_num); \
|
|
} \
|
|
\
|
|
if (ip_header->packet_type == ROHC_PKT_IPV4) \
|
|
{ \
|
|
/* Move pointer back for one IPv4 dynamic part */ \
|
|
/* and IP extension length */ \
|
|
pointer -= (5 + ip_header->ref_len + et0_len); \
|
|
\
|
|
/* Add an IPv4 dynamic part to Dynamic chain */ \
|
|
IPROHC_FMT_IPV4_DYNAMIC(ip_header, &pkt->data[pointer]); \
|
|
} \
|
|
else \
|
|
{ \
|
|
/* Move pointer back for one IPv6 dynamic part */ \
|
|
pointer -= (2 + ip_header->ref_len + et0_len); \
|
|
\
|
|
/* Add an IPv6 dynamic part to Dynamic chain */ \
|
|
IPROHC_FMT_IPV6_DYNAMIC(ip_header, &pkt->data[pointer]); \
|
|
} \
|
|
} \
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* IPROHC_ENCODE_LARGE_CID
|
|
*===========================================================================
|
|
* Encode large CID according to RFC 3095, section 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 octets.
|
|
*/
|
|
#define IPROHC_ENCODE_LARGE_CID(data, pointer, cid, cid_size) \
|
|
{ \
|
|
if (cid < 128) \
|
|
{ \
|
|
/* 0 < cid < 128 (0x80) */ \
|
|
data[pointer] = (Ip_u8)cid; \
|
|
cid_size = 1; \
|
|
} \
|
|
else \
|
|
{ \
|
|
/* 127 (0x7F) < cid < 16384 (0x4000): set the first bit to 1 */ \
|
|
cid |= 0x8000; \
|
|
cid = ip_htons(cid); \
|
|
ipcom_memcpy(&(data[pointer]), &cid, 2); \
|
|
cid_size = 2; \
|
|
} \
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* Public TYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* LOCAL TYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* GLOBAL FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
IP_PUBLIC Ip_err iprohc_fmt_extension(Ipcom_pkt *pkt, int *pointer,
|
|
Iprohc_extension ext_type,
|
|
void *ip_header1, void *ip_header2,
|
|
Ip_u16 sn, Iprohc_mode mode,
|
|
Ip_u8 flags1, Ip_u8 flags2);
|
|
|
|
IP_PUBLIC Ip_u8 iprohc_fmt_base_header(Ip_u8 *base_header,
|
|
Iprohc_c_context *context, void *header1,
|
|
Ip_u8 sn, Ip_u8 crc);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
|
|
#endif /* #ifndef IPROHC_FORMAT_H */
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* END OF FILE
|
|
****************************************************************************
|
|
*/
|
|
|