报头压缩-ROHC数据结构/参数设置

序言

本篇文章将对ROHC压缩的数据结构和参数设置做一些说明,对于使用ROHC协议库进行研究测试提供一定的参考价值。

1. 数据结构

  • 压缩器中定义了一个通用的上下文接口和一个统一的压缩类接口

    • 上下文接口中抽象出了各种类型的上下文中的公有部分,对于各个上下文中的特有部分,上下文接口中提供了一个void*类型的指针来指向它。之所以定义成void类型,是因为不同的上下文对其特有数据的组织方式可以各不相同,因此该指针所指向的数据结构也各不相同。
    • 压缩类接口中定义了许多的函数指针,这些函数指针指向压缩过程中需要使用到的函数。各函数的具体实现由各个压缩类自行决定。
  • 解压器的框架设计和压缩器的完全相同,也包括上下文接口解压类接口

    • 采取这样的设计方法,使得ROHC报头压缩系统具有很好的扩展性和独立性。当出现一种新的报头格式需要进行压缩时,只需要单独定义好该报头类型上下文信息中特有部分的组织方式,然后实现压缩类接口中定义的各个函数,解压器部分再做类似的处理,它就能被很容易的添加进ROHC的体系中来,而对ROHC原有的框架代码不需要做大量的改动。

报头压缩-ROHC数据结构/参数设置_第1张图片

1.1 压缩器数据结构

  • 压缩器中主要定义了三种数据结构:sc_rohc,sc_context,sc_profile。
    • sc_rohc代表压缩器
    • sc_context代表上下文接口
    • sc_profile代表压缩类接口

1.1.1 压缩类接口

  • 压缩类接口字段含义
字段名 含义
id 压缩类的唯一标识,系统中存在4个压缩类
protocol 承载数据包的协议,如RTP、UDP、IP等
version 压缩类的版本号
description 有关压缩类的描述
create 创建压缩时所需要的上下文
destroy 销毁上下文
check_context 检查一个待定的数据包是否属于该上下文
encode 压缩方法
feedback 对解压器发送过来的反馈信息的处理


//压缩类接口 sc_profile
struct sc_profile
{
    unsigned short id;            //Profile的ID
    unsigned short protocol;      //数据包协议
    char *version;                //版本字符串
    char *description;            //描述字符串

    /* 基于给定包,新的context需要初始化时调用 */
    int (*create)(struct sc_context *context, const struct iphdr *packet);

    /* 销毁context中profile特定数据 */
    void (*destroy)(struct sc_context *context);

    /* 检验包是否属于给定的context(使用STATIC-DEF字段等) */
    int (*check_context)(struct sc_context *context, const struct iphdr *packet);

    /* 使用特定context压缩数据包,payload_offset指示payload起始位置 */
    /* 成功返回压缩包大小,错误返回<=0 */
    int (*encode struct sc_context *,const struct iphdr *packet,int packet_size, unsigned char *dest, int dest_size, int *payload_offset);

    /* 当上下文反馈到达时调用 */
    void (*feedback)(struct sc_context *, struct sc_feedback *);
};

1.1.2 上下文接口

  • 上下文接口字段定义
字段名 含义
cid 该上下文的唯一标识
used,last_used,first_used 上下文是否可用,最近使用时间,创建时间
profile_id 上下文所对应的压缩类id
profile 上下文所对应的压缩类
compressor 该上下文所属于的压缩器
c_mode 该上下文所处的模式,包括U,O,R三种模式
c_state 该上下文所处状态,包括NC,SC,FC三种状态
nbo,rnd nbo代表网络字节序,rnd代表IP-ID的值是否随机
data 各上下文中的私有部分,不同上下文它指向的结构不同


//上下文接口 sc_context
struct sc_context
{
    int used;             //1-used,0-unused
    int last_used;        //该上下文被创建的时间
    int first_used;       //该上下文最近使用的时间
    int cid;
    int profile_id;
    struct sc_profile *profile;
    struct sc_rohc *compressor;
    C_MODE c_mode;
    C_STATE c_state;
    int nbo,rnd;

    /* profile的特定数据 */
    void *data;

    /* 统计信息 */
    int total_uncompressed_size,total_compressed_size;
    int header_uncompressed_size,header_compressed_size;
    int send_packets,num_send_ir,num_send_ir_dyn,num_recv_feedbacks;
    struct sc_wlsb *total_16_uncompressed,*total_16_compressed;
    struct sc_wlsb *header_16_uncompressed,*header_16_compressed;
};

1.1.3 压缩器接口

  • 压缩器接口字段含义
字段名 含义
enabled 压缩器是否可以使用
max_cid 支持的最大上下文id值,如果为small_cid,值为16
large_cid 是否使用large_cid,large_cid可以支持65535个上下文
num_used 正在使用中的上下文数量
num_allocated 压缩器已经分配好空间的上下文数量
contexts 指向使用中的上下文的首地址
profiles 标识压缩器所激活的压缩类,1代表激活,一共4类
mrru,connection_type 链路的最大传输单元以及链路的类型


//压缩器接口 sc_rohc
struct sc_rohc
{
    int enabled;
    int max_cid;           //smallCID = [0,15],largeCID = [0,65535]
    int large_cid;
    int num_used;
    int num_allocated;
    struct sc_context *contexts;    //已分配的contexts
    int profiles[C_NUM_PROFILES];
    int mrru;              //Maximum reconstructed reception unit (==0)
    int connnection_type;
    int num_packets;       //已发包的总数
    int total_compressed_size,total_uncompressed_size;
};  


1.2 解压器数据结构

  • 解压器中的数据结构和压缩器中的非常类似,解压器中主要存在三种数据结构:sd_rohc,sd_context,sd_profile。
    • sd_rohc代表解压器
    • sd_context代表解压器中的上下文接口
    • sd_profile代表解压器中的解压类接口

1.2.1 解压类接口

  • 解压类接口字段含义
字段名 含义
id 解压类的唯一标识,系统中存在4个解压类
decode 解压除IR包以外的所有压缩包
decode_ir 解压IR包
allocate_decode_data 为解压器中一个上下文的特有部分数据分配空间
free_decode_data 释放相应的空间
detect_ir_size 得到IR包报头部分长度
detect_ir_dyn_size 得到IR-DYN包报头部分长度
get_sn 取得该上下文中上个成功解压的包的序号


//解压类接口 sd_profile
struct sd_profile
{
    int id;              //0x0000用于未压缩
    char *version;
    char *description;
    int (*decode)(struct sd_rohc *state, struct sd_context *context, unsigned char *src, int size, int second_byte, unsigned char *dest);
    int (*decode_ir)(struct sd_rohc *state, struct sd_context *context, unsigned char *src, int size, int last_bit, unsigned char *dest);
    void *(*allocate_decode_data)(void);
    void (*free_decode_data)(void *);
    int (*detect_ir_size)(unsigned char *first_byte, int second_byte_add);
    int (*detect_ir_dyn_size)(unsign char *first_byte,struct sd_context *context);
    int (*get_sn)(struct sd_context *context);
};

1.2.2 上下文接口

//上下文接口 sd_context
struct sd_context
{
    struct sd_profile *profile;        //已使用的profile
    void *data;                        //profile相关context的数据
    int mode;                          //U_MODE,O_MODE,R_MODE
    int state;                         //NO_CONTEXT,STATIC_CONTEXT,FULL_CONTEXT
    int latest_used,first_used;        //时间戳
    int ack_num;                       //解码成功ack_num++,当ack_num == ACK_NUM解压器生成一个ACK信息

    /* 以下是静态变量 */
    int total_uncompressed_size,total_compressed_size;
    int header_uncompressed_size,header_compressed_size;
    int num_recv_packets,num_recv_ir,num_recv_ir_dyn,num_sent_feedbacks;
    int num_decomp_failures,num_decomp_repairs;
    struct sc_wlsb *total_16_uncompressed,*total_16_compressed;
    struct sc_wlsb *header_16_uncompressed,*header_16_compressed;
};

1.2.3 解压器接口

  • 解压器中字段含义
字段名 含义
context 解压器中的上下文
context_array_size 解压器中上下文的数量
cid_type cid的类型
max_cid 解压器所支持的最大的cid值
compresseor 解压方的压缩器,只存在于双向模式下
statistics 解压器中的统计信息


//解压器 sd_rohc
struct sd_rohc
{
    struct sd_context **context;
    int context_array_size;
    int cid_type;        //large or small cid
    int max_cid;         //最大cid值
    struct sc_rohc *compressor;
    struct sd_statistics statistics;
};


2. 参数设置

在整个ROHC的设计流程中,一些参数:滑动窗口宽度,n1和k1、n2和k2、TIMEOUT_1、TIMEOUT_2、TIMEOUT_3、NO PACKET_1、NO PACKET_2以及NO PACKET_3,会直接影响ROHC的工作性能。

  • 滑动窗口宽度:W-LSB编码中,滑动窗口宽度对压缩效率和健壮性有很重要的影响。当滑动窗口宽度增加时,压缩端使用更多比特数(k增大)进行编码,但只要连续丢包数小于滑动窗口宽度,解压就不会失败,可以说滑动窗口宽度越宽,健壮性越高。
    • U模式下:对于UMTS(移动通信系统)中的RTP/UDP/IP流,滑动窗口宽度从1-14变化时,平均压缩头长度不会变化,因此可以将滑动窗口宽度设置为14以增强健壮性。
    • O模式下:不选用ACK机制,滑动窗口也设置为14
    • R模式下:滑动窗口宽度要大于14,然而R模式中由于总是发送ACK使得滑动窗口收缩,滑动窗口宽度对压缩效率没有影响,在R模式中只需根据健壮性考虑滑动窗口宽度的值。
  • n1,k1,n2,k2:一般将n1、n2设置为相等的值n,k1、k2设置为相等的值k,n和k的值影响着ROHC的健壮性。在三种模式下,k值较小时解压失败率较大,k较大则会增加计算复杂度和存储空间。
    • U模式下:由于发送更新包取决于压缩端的定时设置,随着k的增大,解压失败率趋于稳定。
    • O/R模式下:随着k值的增大,解压失败率先减小到一个最小值,随后又逐渐增大,因为这两种模式发送反馈的时间与k值有关,因为这两种模式发送反馈的时间与k值有关,R模式中使用了7比特和8比特的CRC校验,减少了错误更新上下文的概率,使得接下来的包还是有可能根据正确的上下文解压,相对于O模式,R模式解压失败率增加缓慢。
    • U模式下k值应该较大,O模式和R模式的k值选取范围为从8到20,n的值为(k+(int)k/8)。
  • TIMEOUT_1,TIMEOUT_2,TIMEOUT_3:在U模式中,由于不使用反馈,ROHC的健壮性依赖于定时器,即TIMEOUT_1、TIMEOUT_2和TIMEOUT_3。
    • 定时器值的减少可以增强健壮性,因为更新包发送的频率增加,使得上下文能够经常更新信息,减少了解压失败出现的次数。但定时器值减少的同时,也会降低压缩效率,因为更新包的字节数较大。所以,对于定时器值的选取需要综合考虑健壮性和压缩效率。
    • 用于更新静态信息的包的CRC比特数一般大于用于更新动态信息的包的CRC比特数,因此,上下文中动态信息失同步的概率要大于静态信息,而回到IR状态的定时器也要大于回到FO状态的定时器
    • 综合考虑压缩效率和健壮性,定时器值的选择范围如下:FO_TIMEOUT = TIMEOUT_2 = 90,IR_TIMEOUT = TIMEOUT_3 = TIMEOUT_1取值范围从200到400
  • NO_PACKET_1,NO_PACKET_2,NO_PACKET_3:即压缩端状态转移的n1,n2,n3值。在U模式和O模式的压缩端状态转换中,使用到了参数NO PACKET_1、NO PACKET_2、NO PACKET_3,为简化复杂度,一般将这三个取为相等的值,记为NO PACKET,NO PACKET的值对ROHC的健壮性和压缩效率有着很重要的作用。



Acknowledgements:
[1] 周逻理. 基于 Linux 平台的 ROHC 报头压缩系统的研究与实现[D]. 北京邮电大学, 2008.
[2] 孙青. 基于LTE的健壮性头压缩(ROHC)的研究和实现[D]. 东南大学, 2013.

2017.05.02

你可能感兴趣的:(广播/通信标准/协议)