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