基于Linux内核红黑树的TR069参数解析工具:树形结构+CPE RPC支持

目录

tr069_oid.h

tr069_oid.c

demo.c


tr069_oid.h

/* Dependencies ------------------------------------------------------------------------------------------------------*/

#ifndef __CPE_OID_REG_H
#define __CPE_OID_REG_H 1

#include "easy_macros.h"
#include "rbtree.h"
#include "flog.h"


/* Constants ---------------------------------------------------------------------------------------------------------*/

#define TR069_OID_ITEM_SIZE 64  /* 参数路径单项的最大长度 Device.DeviceInfo.XXXX 中 DeviceInfo的最大长度 */
#define TR069_OID_SIZE      256 /* 参数路径的最大长度  ,Device.DeviceInfo.XXXX 的最大长度             */


/* 参数节点类型 Device.DeviceInfo.1.A  A为叶子,其余为枝干          */
enum TR069_OID_ITEM_TYPE {
    TR069_OID_ITEM_TYPE_BRANCH, //枝干
    TR069_OID_ITEM_TYPE_LEAF    //叶子
};

/* 参数节点Object类型 Device.DeviceInfo.1.A 
                                        ^   Table 矢量,其余为Scalar 标量*/
enum TR069_OID_TYPE {
    TR069_OID_TYPE_TABLE,   //表
    TR069_OID_TYPE_SCALAR,  //标量
};
    

/* Types -------------------------------------------------------------------------------------------------------------*/

struct tr069_oid;
struct tr069_oid_leaf;

/**
 *  参数设置回调函数
 *  说明:
 *      当接口 "tr069_oid_set_parameter_values" 被调用时,该回调函数将被调用。
 *      该回调函数在参数注册时被参数树保存。使用 "tr069_oid_register" 注册。
 *  参数说明:
 *      node        被设置的节点,禁止直接修改该数据结构,会影响参数树的结构。
 *      isObj       参数路径中是否存在可创建/可删除节点,当存在时,其值为真值,否则为假。
 *                  如: 设置 Device.IP.Interface.1.IPv4Address.2.IPAddress,该值为真。
 *      nObj        参数路径中出现的实例号个数。当 isObj 为真时,该参数可用。
 *                  当参数为 Device.IP.Interface.1.IPv4Address.2.IPAddress 时,nObj==2.
 *      ObjInsNums  参数路径中出现的实例号数组。当 isObj 为真时,该参数可用。
 *                  当参数为 Device.IP.Interface.1.IPv4Address.2.IPAddress 时,ObjInsNums[0]==1, ObjInsNums[1] = 2.
 *      argc        用户注册参数个数,该参数为 "tr069_oid_register" 注册时填写 的 "set_argc"。
 *      argv        用户注册参数,该参数为 "tr069_oid_register" 注册时填写 的 "set_argv"。
 */
typedef void (*tr069_oid_set_fn_t)(struct tr069_oid *node, bool isObj, int nObj, int ObjInsNums[], int argc, void *argv[]);

/**
 *  目标创建回调函数
 *  说明:
 *      当接口 "tr069_oid_add_object" 被调用时,该回调函数将被调用。
 *      该回调函数在参数注册时被参数树保存。使用 "tr069_oid_register" 注册。
 *  参数说明:
 *      node        被添加的节点,禁止直接修改该数据结构,会影响参数树的结构。
 *                  当 注册 "Device.IP.Interface.{i}.IPv4Address.{i}.IPAddress" ,可使用 "tr069_oid_add_object" 接口添加实例
 *                  当 tr069_oid_add_object(参数树, Device.IP.Interface.)被调用时,注册的该回调函数将被调用。
 *      currObjIdx  当前添加的实例参数路径中的实例号位置,起始值为 1。
 *                  若支持添加object的参数路径为 Device.A.{i}.{i}.{i}.{i}.{i}.{i}.{i}.{i}.name
 *                  添加一个实例 Device.A. 时, currObjIdx==1
 *                  添加一个实例 Device.A.1. 时, currObjIdx==2
 *                  添加一个实例 Device.A.1.1. 时, currObjIdx==3
 *                  ...
 *                  添加一个实例 Device.A.1.1.1.1.1.1.1. 时, currObjIdx==8
 *
 *      nPrevObj        创建的当前参数路径之前中出现的实例号个数。
 *      prevObjInsNums  创建的当前参数路径之前中出现的实例号。
 *
 *      参数 nPrevObj 和 prevObjInsNums 的例子:
 *                  AddObject: Device.A.        nPrevObj==0,    prevObjInsNums=NULL
 *                  AddObject: Device.A.1.      nPrevObj==1,    prevObjInsNums={1,}
 *                  AddObject: Device.A.1.1.    nPrevObj==2,    prevObjInsNums={1,1,}
 *                      ...
 *                  AddObject: Device.A.1.1.1.2.3.1.1. nPrevObj==8, prevObjInsNums={1,1,1,2,3,1,1,}
 *
 *      argc        用户注册参数个数,该参数为 "tr069_oid_register" 注册时填写 的 "add_argc"。
 *      argv        用户注册参数,该参数为 "tr069_oid_register" 注册时填写 的 "add_argv"。
 *      ObjInsNum   生成的实例号。 1,2,3,4,5...
 *      aliasName   别名:TR069协议规定。
 *
 *  返回值:    
 *      AddObject成功,生成实例号填入 ObjInsNum , 并返回真值。否则返回假。
 */
typedef bool (*tr069_oid_addobj_fn_t)(struct tr069_oid *node, int currObjIdx, int nPrevObj, int prevObjInsNums[], int argc, void *argv[], int *ObjInsNum, char aliasName[TR069_OID_ITEM_SIZE]);

/**
 *  目标删除回调函数
 *  说明:
 *      当接口 "tr069_oid_delete_object" 被调用时,该回调函数将被调用。
 *      该回调函数在参数注册时被参数树保存。使用 "tr069_oid_register" 注册。
 *  参数说明:(见AddObject接口回调   tr069_oid_addobj_fn_t        )
 *      node        被删除的节点,禁止直接修改该数据结构,会影响参数树的结构。
 *      nObj        参数路径中出现的实例号个数。当 isObj 为真时,该参数可用。
 *                  当参数为 Device.IP.Interface.1.IPv4Address.2.IPAddress 时,nObj==2.
 *      ObjInsNums  参数路径中出现的实例号数组。当 isObj 为真时,该参数可用。
 *                  当参数为 Device.IP.Interface.1.IPv4Address.2.IPAddress 时,ObjInsNums[0]==1, ObjInsNums[1] = 2.
 *      argc        用户注册参数个数,该参数为 "tr069_oid_register" 注册时填写 的 "set_argc"。
 *      argv        用户注册参数,该参数为 "tr069_oid_register" 注册时填写 的 "set_argv"。
 */
typedef bool (*tr069_oid_delobj_fn_t)(struct tr069_oid *node, int nObj, int ObjInsNums[], int argc, void *argv[]);



/* TR069 OID树节点结构 */
struct tr069_oid {
    
    char oidNameItem[TR069_OID_ITEM_SIZE];/* 参数路径中的单项名称 */
    char oidAliasNameItem[TR069_OID_ITEM_SIZE];/* 参数单项名称的别名 */
    
    unsigned int oidInstanceNum; /* 实例号 */
    
    enum TR069_OID_ITEM_TYPE node_type; /* 节点单项类型:枝干 或 叶子 */
    enum TR069_OID_TYPE oid_type; /* 目标节点类型:是否可创建,表或标量 */
    
    int writeable; //是否可写
    

    /* 保存下一级 */
    rt_rbtree_t child;  //该节点下的下一级节点
                        //A.B1.C.D
                        //A.B2.C.D
                        //A.B3.C.D
                        //A.child => B1, B2, B3
                        
    struct tr069_oid *father;   //所有节点指向该节点的父节点
                                // A.B.C.D => D.father = &C;
                                
    struct tr069_oid_leaf *leaf_value;    //每个a.b.c.d的叶子"d"需要malloc该块内存
    
    struct tr069_oid_obj_opt *obj_operation; //每个A.{i}.B 中的"{i}"需要malloc该块内存
                                                //并将注册时的参数列表填入该块内存
};


/* TR069 OID树叶子节点数据:供用户使用 */
struct tr069_oid_leaf {
    tr069_oid_set_fn_t set_fn;  /* 参数设置回调函数,在注册参数时提供 */
    int set_argc;/* 参数设置用户参数个数 */
    void **set_argv;/* 参数设置用户参数 */
    char value[TR069_OID_SIZE];/* 参数值 */
    int Notification; /* 参数通知级别:参考TR069协议 *///check in ParameterAttributeStruct, "GetParameterAttribute"
};


/* 目标创建删除用户回调函数 */
struct tr069_oid_obj_opt {
    /* 目标创建 */
    tr069_oid_addobj_fn_t add_fn;
    int add_argc;
    void **add_argv;
    /* 目标删除 */
    tr069_oid_delobj_fn_t del_fn;
    int del_argc;
    void **del_argv;
};


/* TR069 OID路径名结构 */
struct tr069_oid_names {
    int count;/* 获取的参数名个数 */
    ParameterInfoStruct *NameList;/* 参数名 */
};


/* TR069 OID 值结构 */
struct tr069_oid_values {
    int count;/* 获取的参数值的个数 */
    ParameterValueStruct *ValueList;/* 参数值 */
};


/* TR069 OID 属性值结构 */
struct tr069_oid_attrs {
    int count;/* 参数属性个数 */
    ParameterAttributeStruct *AttrList;/* 参数属性 */
};


/* Macros ------------------------------------------------------------------------------------------------------------*/

#define TR069_OID_GetParamNamesShow(tree, str, nextlevel, printfn) \
    {\
        printfn("\n--------------GetParamNames %s--------------\n", str); \
        struct tr069_oid_names *__names = tr069_oid_get_parameter_names(tree, str, nextlevel);\
        int __inames;\
        for(__inames=0;__inames<__names->count;__inames++) {\
            printfn(">> %d/%d:{ \"parameter\": \"%s\", \"writable\": \"%d\" }\n", \
                        __inames, __names->count, __names->NameList[__inames].Name, __names->NameList[__inames].Writable);\
        }\
        printfn("------------------------------------------------------\n");\
        tr069_oid_get_parameter_names_free(__names);\
    }


#define TR069_OID_GetParamValuesShow(tree, str, printfn) \
    {\
        printfn("\n-----------GetParamValues %s-----------\n", str); \
        struct tr069_oid_values *__values = tr069_oid_get_parameter_values(tree, str);\
        int __ivalues;\
        for(__ivalues=0;__ivalues<__values->count;__ivalues++) {\
            printfn(">> %d/%d:{ \"parameter\": \"%s\", \"value\": \"%s\" }\n", \
                        __ivalues, __values->count, __values->ValueList[__ivalues].Name, __values->ValueList[__ivalues].Value);\
        }\
        printfn("------------------------------------------------------\n");\
        tr069_oid_get_parameter_values_free(__values);\
    }


#define TR069_OID_GetParamAttributeShow(tree, str, printfn) \
    {\
        printfn("\n------------GetParamAttribute %s------------\n", str); \
        struct tr069_oid_attrs *__attrs = tr069_oid_get_parameter_attributes(tree, str);\
        int __iattrs;\
        for(__iattrs=0;__iattrs<__attrs->count;__iattrs++) {\
            printfn(">> %d/%d:{ \"parameter\": \"%s\", \"notification\": \"%d\" }\n", \
                        __iattrs, __attrs->count, __attrs->AttrList[__iattrs].Name, __attrs->AttrList[__iattrs].Notification);\
        }\
        printfn("------------------------------------------------------\n");\
        tr069_oid_get_parameter_attributes_free(__attrs);\
    }

/* Globals -----------------------------------------------------------------------------------------------------------*/


/* Functions ---------------------------------------------------------------------------------------------------------*/
/**
 *  参数树的创建/初始化 与 摧毁
 */
rt_rbtree_t tr069_oid_tree_create();
void tr069_oid_tree_destroy(rt_rbtree_t oid_root);

/**
 *  参数注册
 *  函数说明:
 *      当使用 接口 tr069_oid_tree_create 创建参数树后,可以使用该接口注册一个参数。
 *  函数参数列表:
 *      oid_root        参数树
 *      ParameterPath   一个完整的参数路径, 如 "Device.IP.Interface.{i}.IPv4Address.{i}.IPAddress"
 *      writeable       是否可写(0-不可写,1-可写),值得一提的是,该值只决定了 ParameterPath 路径规定的最后一个参数,而其他参数的可写性,
 *                      由接口内部决定,如 参数 "Device.IP.Interface.{i}.IPv4Address.{i}.IPAddress" 的可写性为:
 *                      可写的有:         Interface IPv4Address 
 *                      不可写的有:  Device IP {i} 
 *                      由参数 writeable 决定 IPAddress 是否可写
 *      default_value   一个默认值,字符串形式
 *      Notification    通知级别,参考TR069协议中的 ParameterAttributeStruct 结构,取值 0~6
 *      set_fn          参考 tr069_oid_set_fn_t 
 *      set_argc        set_fn 的入参
 *      set_argv        set_fn 的入参
 *      add_fn          参考 tr069_oid_addobj_fn_t 
 *      add_argc        add_fn 的入参
 *      add_argv        add_fn 的入参
 *      del_fn          参考 tr069_oid_delobj_fn_t 
 *      del_argc        del_fn 的入参
 *      del_argv        del_fn 的入参
 */
int tr069_oid_register(rt_rbtree_t oid_root, char ParameterPath[TR069_OID_SIZE], 
                         int writeable, char default_value[TR069_OID_SIZE], int Notification,
                         tr069_oid_set_fn_t set_fn, int set_argc, void *set_argv[],
                         tr069_oid_addobj_fn_t add_fn, int add_argc, void *add_argv[],
                         tr069_oid_delobj_fn_t del_fn, int del_argc, void *del_argv[]);

/**
 *  参数轮询
 *  函数说明:
 *      该参数将轮询此树的所有节点, display 将被调用。 遗憾的是, oid 将不被允许修改, 否则会捣乱树结构, oid只读。
 *  函数参数列表:
 *      oid_root    参数树
 *      display     轮询树是被调用的回调函数
 *                  oid 参数节点
 *                  arg 用户数据
 *      arg         用户数据, 将被透传至 display 的参数列表中
 */
void tr069_oid_display(rt_rbtree_t oid_root, void (*display)(struct tr069_oid *oid, void *arg), void *arg);

/**
 *  参数名获取
 *  函数说明:
 *      GetParameterNames 
 *  函数参数列表:
 *      oid_root    参数树
 *      pathPrefix  参数路径, 如 "Device."
 *      nextlevel   是否只获取下一级参数节点, 取值0或1,参考标准协议。
 *  返回值   
 *      结构 struct tr069_oid_names 该结构需要使用 tr069_oid_get_parameter_names_free 进行释放
 *      
 */
struct tr069_oid_names *tr069_oid_get_parameter_names(rt_rbtree_t oid_root, char pathPrefix[TR069_OID_SIZE], int nextlevel);
void tr069_oid_get_parameter_names_free(struct tr069_oid_names *oid_names);

/**
 *  参数获取
 *  函数说明:
 *      GetParameterValues
 *  函数参数列表:
 *      oid_root    参数树
 *      pathPrefix  参数路径, 如 "Device."
 *  返回值
 *      结构    struct tr069_oid_values   , 需要使用 tr069_oid_get_parameter_values_free 释放内存
 *      
 *      
 */
struct tr069_oid_values *tr069_oid_get_parameter_values(rt_rbtree_t oid_root, char pathPrefix[TR069_OID_SIZE]);
void tr069_oid_get_parameter_values_free(struct tr069_oid_values *oid_values);

/**
 *  参数设置
 *  函数说明:
 *      SetParameterValues
 *  函数参数列表:
 *      oid_root    参数树
 *      paramPath   参数的完整路径, 如 "Device.IPsec.Enable"
 *      paramValue  参数值, 字符串
 *  返回值
 *      结构 struct tr069_oid, 很遗憾, 这个返回值不许修改,否则会损坏树结构。
 */
struct tr069_oid *tr069_oid_set_parameter_values(rt_rbtree_t oid_root, char paramPath[TR069_OID_SIZE], char paramValue[TR069_OID_SIZE]);

/**
 *  参数属性获取
 *  函数说明:
 *      GetParamAttributes
 *  函数参数列表:
 *      oid_root    参数树
 *      pathPrefix  参数路径, 如 "Device."
 *  返回值
 *      结构      struct tr069_oid_attrs, 需要使用 tr069_oid_get_parameter_attributes_free 释放内存
 */
struct tr069_oid_attrs *tr069_oid_get_parameter_attributes(rt_rbtree_t oid_root, char pathPrefix[TR069_OID_SIZE]);
void tr069_oid_get_parameter_attributes_free(struct tr069_oid_attrs *oid_attrs);

/**
 *  参数属性设置
 *  函数说明:
 *      SetParamAttributes
 *  函数参数列表:
 *      oid_root    参数树
 *      paramPath   参数的完整路径, 如 "Device.IPsec.Enable"
 *      Notification    通知级别,参考TR069协议中的 ParameterAttributeStruct 结构,取值 0~6
 *  返回值
 *      结构 struct tr069_oid, 很遗憾, 这个返回值不许修改,否则会损坏树结构。
 */
struct tr069_oid *tr069_oid_set_parameter_attributes(rt_rbtree_t oid_root, char paramPath[TR069_OID_SIZE], int Notification);

/**
 *  目标实例添加和删除
 *  函数说明:
 *      AddObject DeleteObject
 *  函数参数列表:
 *      oid_root        参数树
 *      ParameterPath   参数路径, 如 注册了 Device.IP.Interface.{i}.IPv4Address.{i}.IPAddress
 *                      此时 Device.IP.Interface. 是支持 AddObject 的,当 调用了 tr069_oid_add_object , 参见注册接口:
 *                      tr069_oid_register 的 add_fn 将被调用, 需要生成   实例号。
 *      pathPrefix      参数路径, 如添加了目标实例 1,-> 可使用 "Device.IP.Interface.1." 对其进行删除, 可调用该接口删除该实例。
 *  返回值
 *      tr069_oid_add_object 成功返回实例号, 失败返回 VOS_ERROR
 *      
 */
int tr069_oid_add_object(rt_rbtree_t oid_root, char ParameterPath[TR069_OID_SIZE]);
int tr069_oid_delete_object(rt_rbtree_t oid_root, char pathPrefix[TR069_OID_SIZE]);






#endif //__CPE_OID_REG_H

tr069_oid.c

   
/* Dependencies ------------------------------------------------------------------------------------------------------*/
#include <stdio.h>
#include <sys/types.h>
#include <regex.h>


#include "tr069_oid.h"

/* Types -------------------------------------------------------------------------------------------------------------*/



/* Constants ---------------------------------------------------------------------------------------------------------*/
#define TABLE_NODE "TABLE"


/* Macros ------------------------------------------------------------------------------------------------------------*/
/* Globals -----------------------------------------------------------------------------------------------------------*/
    
/* Functions ---------------------------------------------------------------------------------------------------------*/

/* 正则化检验参数字符串是否合法 
 *  例如:Device.FaultMgmt.ExpeditedEvent.{2}.PerceivedSeverity
 */
static int _unused oid_string_pattern_check(char *oidString)
{
#define OID_REGEX_PATTERN "^Device\\.[a-zA-Z]\\w+\\.(([a-zA-Z0-9]\\w+|\\{[0-9a-z]\\})\\.)*[a-zA-Z0-9]\\w+"
//                           ^Device\\.[a-zA-Z]\\w+\\.(([a-zA-Z]\\w+|\\{[0-9a-z]\\})\\.)*[a-zA-Z0-9]\\w+

    int ret = VOS_ERROR;
	int status = 0;
	int flag = REG_EXTENDED;
	regmatch_t pmatch[1];
	const size_t nmatch = 1;
	regex_t reg;
	const char *pattern = OID_REGEX_PATTERN;
    
	regcomp(&reg, pattern, flag);
	status = regexec(&reg, oidString, nmatch, pmatch, 0);
	if(status == REG_NOMATCH){
        ret = VOS_ERROR;
	}else if(status == 0){
        ret = VOS_OK;
	}
	regfree(&reg);

	return ret;
}


/* OID 节点项的对比函数 */
static int _unused __tr069_oid_node_cmp(void *d1, void *d2)
{
    struct tr069_oid *oid1 = d1, *oid2 = d2;
    char *oidName1 = oid1->oidNameItem;
    char *oidName2 = oid2->oidNameItem;
    
    if(strncmp(oidName1, oidName2, TR069_OID_ITEM_SIZE) > 0) return GT;
    else if(strncmp(oidName1, oidName2, TR069_OID_ITEM_SIZE) == 0) return EQ;
    else if(strncmp(oidName1, oidName2, TR069_OID_ITEM_SIZE) < 0) return LT;

    return EQ;
}

/* OID 树的创建 */
static void _unused __tr069_oid_tree_create(rt_rbtree_t *tree)
{
    *tree = rt_rbtree_init_nonmalloc("OIDTree", __tr069_oid_node_cmp);
}

/* 初始化OID的树的根 */
rt_rbtree_t tr069_oid_tree_create()
{
    rt_rbtree_t oid_root;
    __tr069_oid_tree_create(&oid_root);
    return oid_root;
}

/* 获取参数名中Item的项数
 *  例如:Device.FaultMgmt.ExpeditedEvent.{2}.PerceivedSeverity 返回 5
 */
static int _unused __get_N_item(char path[TR069_OID_SIZE])
{
    int iItem = 0;
    int iChar = 0;
    int len = strlen(path);
    
    while(path[iChar] != '\0' && iChar <= len) {
        while(path[iChar] != '.' && path[iChar] != '\0') {
            iChar++;
        }
        iItem++;
        iChar++;
    }
    return iItem;
}

/* 获取参数名中某一项的 名称
 *  例如:
 *      ParameterPath = Device.FaultMgmt.ExpeditedEvent.{2}.PerceivedSeverity 
 *      iItem = 2
 *   那么, oidNameItem = FaultMgmt
 */
static int _unused __get_I_item_name(char path[TR069_OID_SIZE], int iItem, char oidNameItem[TR069_OID_ITEM_SIZE])
{
    int __iItem = 0;
    int iChar = 0;
    int len = strlen(path);
    
    while(path[iChar] != '\0' && iChar <= len) {
        memset(oidNameItem, 0, TR069_OID_ITEM_SIZE);
        int i = 0;
        while(path[iChar] != '.' && path[iChar] != '\0') {
            oidNameItem[i++] = path[iChar++];
        }
        oidNameItem[i] = '\0';
        __iItem++;
        iChar++;
        if(__iItem == iItem) {
            return iItem;
        }
    }
    return -1;
}


/* 向树种递归添加节点,若不存在该节点则创建 */
static struct tr069_oid * _unused 
__oid_tree_add_node(struct tr069_oid *father, rt_rbtree_t tree, char currPath[TR069_OID_SIZE], 
                        int writeable, char *defaultValue, int Notification, 
                        tr069_oid_set_fn_t set_fn, int set_argc, void *set_argv[],
                        tr069_oid_addobj_fn_t add_fn, int add_argc, void *add_argv[],
                        tr069_oid_delobj_fn_t del_fn, int del_argc, void *del_argv[])
{
    /* OID名称 */
    char oidNameItem[TR069_OID_ITEM_SIZE] = {0};
    char oidNameItemTmp[TR069_OID_ITEM_SIZE] = {0};
    memset(oidNameItem, 0, TR069_OID_ITEM_SIZE);
    memset(oidNameItemTmp, 0, TR069_OID_ITEM_SIZE);

    /* 获取项数 */
    int nItem = __get_N_item(currPath);
    __get_I_item_name(currPath, 1, oidNameItem);/* 解析出第一项名称 */

    /* 是否为“{3}”类型   */
    int oidTableNode = 0;
    if(oidNameItem[0] == '{') {
        oidTableNode = 1;
        if(!add_fn || !del_fn) {
            vos_err_print("Error: Must fill 'add_fn' and 'del_fn' when register a addable object OID.\n");
            return NULL;
        }
    }
    
    /* 申请内存 */
    struct tr069_oid *new_node = malloc(sizeof(struct tr069_oid));
    VOS_MemZero(new_node->oidNameItem, TR069_OID_ITEM_SIZE);
    VOS_MemZero(new_node->oidAliasNameItem, TR069_OID_ITEM_SIZE);

    new_node->obj_operation = NULL;
    new_node->leaf_value = NULL;
    
    new_node->father = father;

    if(oidTableNode) {
        VOS_Snprintf(oidNameItemTmp, TR069_OID_ITEM_SIZE, TABLE_NODE);
        new_node->father->writeable = 1;
        new_node->oid_type = TR069_OID_TYPE_TABLE;
        
        new_node->obj_operation = malloc(sizeof(struct tr069_oid_obj_opt ));

        new_node->obj_operation->add_fn = add_fn;
        new_node->obj_operation->add_argc = add_argc;
        new_node->obj_operation->add_argv = add_argv;
        
        new_node->obj_operation->del_fn = del_fn;
        new_node->obj_operation->del_argc = del_argc;
        new_node->obj_operation->del_argv = del_argv;
    } else {
        VOS_StrCpy(oidNameItemTmp, oidNameItem);
        
        if(nItem == 1) {
            new_node->writeable = writeable; //叶子
            new_node->node_type = TR069_OID_ITEM_TYPE_LEAF;
        } else {
            new_node->writeable = 0; //枝干不可写
            new_node->node_type = TR069_OID_ITEM_TYPE_BRANCH;
        }
        new_node->oid_type = TR069_OID_TYPE_SCALAR;
    }
    VOS_StrCpy(new_node->oidNameItem, oidNameItemTmp);
    new_node->oidInstanceNum = 0;
    
    int exist_flag = 0;

    rt_rbtree_node_t *node = rt_rbtree_search(tree, new_node);
    if( node ) { //已存在的节点
        if(oidTableNode) {
            free(new_node->obj_operation);
        }
        free(new_node);
        new_node = node->data;
        new_node->father = father;
        
        if(nItem != 1) {
            new_node->node_type = TR069_OID_ITEM_TYPE_BRANCH;
        } else if(nItem == 1) {
            new_node->writeable = writeable; //叶子
            new_node->node_type = TR069_OID_ITEM_TYPE_LEAF;
        }
        exist_flag = 1;
        
    } else {    //不存在该节点
        exist_flag = 0;
        
        
        __tr069_oid_tree_create(&new_node->child);
        rt_rbtree_insert(tree, new_node, sizeof(struct tr069_oid));
    }
    /* 若为最后一项:叶子节点 */
    if(nItem == 1) {
        if(exist_flag) return NULL;
        
        new_node->node_type = TR069_OID_ITEM_TYPE_LEAF;
        new_node->writeable = writeable; //只设置最后一个叶子节点
        
        new_node->leaf_value = malloc(sizeof(struct tr069_oid_leaf));
        VOS_StrnCpy(new_node->leaf_value->value, defaultValue, TR069_OID_SIZE);

        new_node->leaf_value->Notification = Notification;
        new_node->leaf_value->set_fn = set_fn;
        new_node->leaf_value->set_argc = set_argc;
        new_node->leaf_value->set_argv = set_argv;
        
        return new_node;

    /* 非叶子节点,递归添加 */
    } else {
        new_node->node_type = TR069_OID_ITEM_TYPE_BRANCH;
        new_node->leaf_value = NULL;
//        new_node->writeable = 0; //枝干不可写
        int iChar = 0;
        while(currPath[iChar++] != '.');
        __oid_tree_add_node(new_node, new_node->child, &currPath[iChar], writeable, defaultValue, Notification, 
                            set_fn, set_argc, set_argv, add_fn, add_argc, add_argv, del_fn, del_argc, del_argv);
    }
    
    return NULL;
}



/* 获取路径下的项 */
static struct tr069_oid _unused* __oid_tree_find_oid_path(rt_rbtree_t tree, char currPath[TR069_OID_SIZE])
{
    char oidNameItem[TR069_OID_ITEM_SIZE] = {0};
    memset(oidNameItem, 0, TR069_OID_ITEM_SIZE);
    
    int nItem = __get_N_item(currPath);
    __get_I_item_name(currPath, 1, oidNameItem);


    struct tr069_oid *find_node = malloc(sizeof(struct tr069_oid));
    memset(find_node->oidNameItem, 0, TR069_OID_ITEM_SIZE);
    memset(find_node->oidAliasNameItem, 0, TR069_OID_ITEM_SIZE);
    
//    VOS_MemZero(find_node->ParameterPath, TR069_OID_SIZE);
    VOS_StrCpy(find_node->oidNameItem, oidNameItem);
    
    rt_rbtree_node_t *node = rt_rbtree_search(tree, find_node);
    if( node ) { //存在该节点
        free(find_node);
        find_node = node->data;
        
        if(nItem == 1) {
            return find_node;
        } else {
            int iChar = 0;
            while(currPath[iChar++] != '.');
            return __oid_tree_find_oid_path(find_node->child, &currPath[iChar]);
        }
    }
    return NULL;
}


/* 递归获取树下面所有的节点数 */
static int _unused __oid_tree_subcount(rt_rbtree_t tree, int nextlevel)
{
    int count = 0;
    struct tr069_oid *this_oid = NULL;
    rt_rbtree_node_t *node = NULL;
    for(node = rt_rbtree_getfirst(tree); node; node=rt_rbtree_getnext(node)) {
        this_oid = node->data;
        if(VOS_StrnCmp(TABLE_NODE, this_oid->oidNameItem, TR069_OID_ITEM_SIZE) == 0) continue;
        count++;
        if(!nextlevel) {
            count += __oid_tree_subcount(this_oid->child, nextlevel);
        }
    }
    return count;
}

/* 递归获取树下面所有的叶子节点数 */
static int _unused __oid_tree_subleafcount(rt_rbtree_t tree)
{
    int count = 0;
    struct tr069_oid *this_oid = NULL;
    rt_rbtree_node_t *node = NULL;
    for(node = rt_rbtree_getfirst(tree); node; node=rt_rbtree_getnext(node)) {
        this_oid = node->data;

        if(VOS_StrnCmp(TABLE_NODE, this_oid->oidNameItem, TR069_OID_ITEM_SIZE) == 0) continue;
    
        if(this_oid->node_type == TR069_OID_ITEM_TYPE_LEAF) {
            count++;
            continue;
        }
        count += __oid_tree_subleafcount(this_oid->child);
    }
    return count;
}

/* 递归获取树下面所有的节点数 */
static void __tr069_oid_oids_get(struct tr069_oid *oid, ParameterInfoStruct *NameList, int *ioid, int nextlevel)
{
    struct tr069_oid *this_oid = NULL;
    rt_rbtree_node_t *node = NULL;


    for(node = rt_rbtree_getfirst(oid->child); node; node=rt_rbtree_getnext(node), this_oid = NULL) {
        this_oid = node->data;
        
    
        if(VOS_StrnCmp(TABLE_NODE, this_oid->oidNameItem, TR069_OID_ITEM_SIZE) == 0) continue;
        
        VOS_MemZero(NameList[*ioid].Name, sizeof(char)*TR069_OID_SIZE);
        NameList[*ioid].Writable = this_oid->writeable;
        
        char tmp[TR069_OID_SIZE] = {0};
        struct tr069_oid *tmp_oid = NULL;
        for(tmp_oid = this_oid; tmp_oid; tmp_oid = tmp_oid->father) {
            
            VOS_MemZero(tmp, TR069_OID_SIZE);
            VOS_StrCat(tmp, NameList[*ioid].Name);
            VOS_Sprintf(NameList[*ioid].Name, "%s%s%s", tmp_oid->oidNameItem, 
                                                   tmp_oid->node_type==TR069_OID_ITEM_TYPE_LEAF?"":".", 
                                                   tmp);
        }
        
        (*ioid)++;
        if(!nextlevel && this_oid) { //如果不止获取下一级节点
            __tr069_oid_oids_get(this_oid, NameList, ioid, nextlevel);
        }
    }
}

/* 递归获取树下面所有的叶子节点数 */
static void __tr069_oid_oids_getleaf_value(struct tr069_oid *oid, ParameterValueStruct *ValuesList, int *ioid)
{
    struct tr069_oid *this_oid = NULL;
    rt_rbtree_node_t *node = NULL;


    for(node = rt_rbtree_getfirst(oid->child); node; node=rt_rbtree_getnext(node), this_oid = NULL) {
        this_oid = node->data;

        if(VOS_StrnCmp(TABLE_NODE, this_oid->oidNameItem, TR069_OID_ITEM_SIZE) == 0) continue;
        
        if(this_oid->node_type == TR069_OID_ITEM_TYPE_LEAF) {
            char tmp[TR069_OID_SIZE] = {0};
            struct tr069_oid *tmp_oid = NULL;
            for(tmp_oid = this_oid; tmp_oid; tmp_oid = tmp_oid->father) {
                
                VOS_MemZero(tmp, TR069_OID_SIZE);
                VOS_StrCat(tmp, ValuesList[*ioid].Name);
                VOS_Sprintf(ValuesList[*ioid].Name, "%s%s%s", tmp_oid->oidNameItem, 
                                                       tmp_oid->node_type==TR069_OID_ITEM_TYPE_LEAF?"":".", 
                                                       tmp);
            }
//            printf("%s: %s\n", tmp_oid->oidNameItem, oid_values->ValueList[i].Name);
            VOS_StrnCpy(ValuesList[*ioid].Value, this_oid->leaf_value->value, TR069_OID_SIZE);
            (*ioid)++;
            continue;
        } else {
             __tr069_oid_oids_getleaf_value(this_oid, ValuesList, ioid);
        }
        
    }
}


/* 递归获取树下面所有的叶子节点数 */
static void __tr069_oid_oids_getleaf_attr(struct tr069_oid *oid, ParameterAttributeStruct *AttrsList, int *ioid)
{
    struct tr069_oid *this_oid = NULL;
    rt_rbtree_node_t *node = NULL;


    for(node = rt_rbtree_getfirst(oid->child); node; node=rt_rbtree_getnext(node), this_oid = NULL) {
        this_oid = node->data;

        if(VOS_StrnCmp(TABLE_NODE, this_oid->oidNameItem, TR069_OID_ITEM_SIZE) == 0) continue;
        
        if(this_oid->node_type == TR069_OID_ITEM_TYPE_LEAF) {
            char tmp[TR069_OID_SIZE] = {0};
            struct tr069_oid *tmp_oid = NULL;
            for(tmp_oid = this_oid; tmp_oid; tmp_oid = tmp_oid->father) {
                
                VOS_MemZero(tmp, TR069_OID_SIZE);
                VOS_StrCat(tmp, AttrsList[*ioid].Name);
                VOS_Sprintf(AttrsList[*ioid].Name, "%s%s%s", tmp_oid->oidNameItem, 
                                                       tmp_oid->node_type==TR069_OID_ITEM_TYPE_LEAF?"":".", 
                                                       tmp);
            }
//            printf("%s: %s\n", tmp_oid->oidNameItem, oid_values->ValueList[i].Name);
            AttrsList[*ioid].Notification = this_oid->leaf_value->Notification;
            (*ioid)++;
            continue;
        } else {
             __tr069_oid_oids_getleaf_attr(this_oid, AttrsList, ioid);
        }
        
    }
}


/* 注册一个参数 */
int tr069_oid_register(rt_rbtree_t oid_root, char absolutePath[TR069_OID_SIZE], 
                         int writeable, char default_value[TR069_OID_SIZE], int Notification,
                         tr069_oid_set_fn_t set_fn, int set_argc, void *set_argv[],
                         tr069_oid_addobj_fn_t add_fn, int add_argc, void *add_argv[],
                         tr069_oid_delobj_fn_t del_fn, int del_argc, void *del_argv[])
{
    if(VOS_OK != oid_string_pattern_check(absolutePath)) {
        vos_err_print("TR069 Notmatch: %s\n", absolutePath);
        return VOS_ERROR;
    }
    if(!default_value ) {//必须有默认值
        vos_err_print("TR069 must need default value.\n");
        return VOS_ERROR;
    }
    struct tr069_oid *oid = __oid_tree_add_node(NULL, oid_root, absolutePath, writeable, default_value, Notification, 
                                                set_fn, set_argc, set_argv, add_fn, add_argc, add_argv, del_fn, del_argc, del_argv);
    if(oid) {
        return VOS_OK;
    } else {
//        vos_warning_print("Exist Node: %s\n", absolutePath);
        return VOS_ERROR;
    }
    
    return VOS_OK;
}



/* 递归操作一个OID */
static void __tr069_oid_display(rt_rbtree_t this_tree, void (*display)(struct tr069_oid *oid, void *arg), void *arg)
{
    if(!this_tree) return;

    struct tr069_oid *this_oid = NULL;
    rt_rbtree_node_t *node = NULL;
    for(node = rt_rbtree_getfirst(this_tree); node; node=rt_rbtree_getnext(node)) {
        this_oid = node->data;
        display(this_oid, arg);
        __tr069_oid_display(this_oid->child, display, arg);
    }
}

/* 操作一个OID */
_api void tr069_oid_display(rt_rbtree_t oid_root, void (*display)(struct tr069_oid *oid, void *arg), void *arg) 
{
    __tr069_oid_display(oid_root, display, arg);
}

/* GetParameterNames */
_api struct tr069_oid_names *
tr069_oid_get_parameter_names(rt_rbtree_t oid_root, char pathPrefix[TR069_OID_SIZE], int nextlevel)
{
    int count = 0;
    
    struct tr069_oid_names *oid_names = malloc(sizeof(struct tr069_oid_names));
    oid_names->count = 0;
    oid_names->NameList = NULL;
    
    struct tr069_oid * oid_item = __oid_tree_find_oid_path(oid_root, pathPrefix);
    if(!oid_item) {
        vos_err_print("Not exist ParamPath: %s\n", pathPrefix);
        return oid_names;
    }
    if(!nextlevel) (count)++;
    count += __oid_tree_subcount(oid_item->child, nextlevel);

    oid_names->count = count;
    oid_names->NameList = malloc(sizeof(ParameterInfoStruct)*(count));
    
    int i = 0;
    if(!nextlevel) {
        strcpy(oid_names->NameList[i].Name, pathPrefix);
        oid_names->NameList[i].Writable = oid_item->writeable;
        (i)++;
    }
    __tr069_oid_oids_get(oid_item, oid_names->NameList, &i, nextlevel);    
    
    return oid_names;
}


/* GetParameterNames Free */
_api void tr069_oid_get_parameter_names_free(struct tr069_oid_names *oid_names)
{
    if(!oid_names)
        return;
    free(oid_names->NameList);
    free(oid_names);
}

/* 查询一个参数 */
/* GetParameterValues */
_api struct tr069_oid_values *
tr069_oid_get_parameter_values(rt_rbtree_t oid_root, char pathPrefix[TR069_OID_SIZE])
{
    int count = 0;
    
    struct tr069_oid_values *oid_values = malloc(sizeof(struct tr069_oid_values));
    oid_values->count = 0;
    oid_values->ValueList = NULL;
    
    struct tr069_oid * oid_item = __oid_tree_find_oid_path(oid_root, pathPrefix);
    if(!oid_item) {
        vos_err_print("Not exist ParamPath: %s\n", pathPrefix);
        return oid_values;
    }
    if(oid_item->node_type == TR069_OID_ITEM_TYPE_LEAF) {
        count ++;
    }
    count += __oid_tree_subleafcount(oid_item->child);
//    vos_err_print("count = %d\n", count);
    
    oid_values->count = count;
    oid_values->ValueList = malloc(sizeof(ParameterValueStruct)*(count));
    VOS_MemZero(oid_values->ValueList, sizeof(ParameterValueStruct)*(count));
    
    int i = 0;
//    printf(">>>%s\n", oid_values->ValueList[i].Name);
    
    /* 如果是叶子 */
    if(oid_item->node_type == TR069_OID_ITEM_TYPE_LEAF) {
        
char tmp[TR069_OID_SIZE] = {0};
        struct tr069_oid *tmp_oid = NULL;
        for(tmp_oid = oid_item; tmp_oid; tmp_oid = tmp_oid->father) {
            
            VOS_MemZero(tmp, TR069_OID_SIZE);
            VOS_StrCat(tmp, oid_values->ValueList[i].Name);
            VOS_Sprintf(oid_values->ValueList[i].Name, "%s%s%s", tmp_oid->oidNameItem, 
                                                   tmp_oid->node_type==TR069_OID_ITEM_TYPE_LEAF?"":".", 
                                                   tmp);
        }
        (i)++;

    } else {
        __tr069_oid_oids_getleaf_value(oid_item, oid_values->ValueList, &i);
    }
    return oid_values;
}

/* GetParameterValues Free */
_api void tr069_oid_get_parameter_values_free(struct tr069_oid_values *oid_values)
{
    if(!oid_values)
        return;
    free(oid_values->ValueList);
    free(oid_values);
}



/* 查询一个参数 */
/* GetParameterAttribute */
_api struct tr069_oid_attrs *
tr069_oid_get_parameter_attributes(rt_rbtree_t oid_root, char pathPrefix[TR069_OID_SIZE])
{
    int count = 0;
    
    struct tr069_oid_attrs *oid_attrs = malloc(sizeof(struct tr069_oid_attrs));
    oid_attrs->count = 0;
    oid_attrs->AttrList = NULL;
    
    struct tr069_oid * oid_item = __oid_tree_find_oid_path(oid_root, pathPrefix);
    if(!oid_item) {
        vos_err_print("Not exist ParamPath: %s\n", pathPrefix);
        return oid_attrs;
    }
    if(oid_item->node_type == TR069_OID_ITEM_TYPE_LEAF) {
        count ++;
    }
    count += __oid_tree_subleafcount(oid_item->child);
//    vos_err_print("count = %d\n", count);
    
    oid_attrs->count = count;
    oid_attrs->AttrList = malloc(sizeof(ParameterAttributeStruct)*(count));
    VOS_MemZero(oid_attrs->AttrList, sizeof(ParameterAttributeStruct)*(count));
    
    int i = 0;
    
    /* 如果是叶子 */
    if(oid_item->node_type == TR069_OID_ITEM_TYPE_LEAF) {
        
char tmp[TR069_OID_SIZE] = {0};
        struct tr069_oid *tmp_oid = NULL;
        for(tmp_oid = oid_item; tmp_oid; tmp_oid = tmp_oid->father) {
            
            VOS_MemZero(tmp, TR069_OID_SIZE);
            VOS_StrCat(tmp, oid_attrs->AttrList[i].Name);
            VOS_Sprintf(oid_attrs->AttrList[i].Name, "%s%s%s", tmp_oid->oidNameItem, 
                                                   tmp_oid->node_type==TR069_OID_ITEM_TYPE_LEAF?"":".", 
                                                   tmp);
        }
        (i)++;

    } else {
        __tr069_oid_oids_getleaf_attr(oid_item, oid_attrs->AttrList, &i);
    }
    return oid_attrs;
}


/* GetParameterValues Free */
_api void tr069_oid_get_parameter_attributes_free(struct tr069_oid_attrs *oid_attrs)
{
    if(!oid_attrs)
        return;
    free(oid_attrs->AttrList);
    free(oid_attrs);
}


static void _unused __tr069_tree_obj_count(struct tr069_oid * oid_tail, int **instanceNums, int *instanceCount)
{
    *instanceCount = 0;
    struct tr069_oid *tmp_oid = NULL;
    for(tmp_oid = oid_tail; tmp_oid; tmp_oid = tmp_oid->father) {
        
        if(tmp_oid->oidInstanceNum) {
            (*instanceCount)++;
            if(*instanceCount == 1) {
                *instanceNums = malloc(sizeof(int)*(*instanceCount));
            } else {
                *instanceNums = realloc(*instanceNums, sizeof(int)*(*instanceCount));
            }
            (*instanceNums)[(*instanceCount)-1] = tmp_oid->oidInstanceNum;
        }
    }
    int i;
    for(i=0; i<*instanceCount/2;i++) {
        (*instanceNums)[i] += (*instanceNums)[*instanceCount-1-i];
        (*instanceNums)[*instanceCount-1-i] = (*instanceNums)[i] - (*instanceNums)[*instanceCount-1-i];
        (*instanceNums)[i] -= (*instanceNums)[*instanceCount-1-i];
    }
}

struct tr069_oid *tr069_oid_set_parameter_values(rt_rbtree_t oid_root, char paramPath[TR069_OID_SIZE], char paramValue[TR069_OID_SIZE])
{
    struct tr069_oid * oid_item = __oid_tree_find_oid_path(oid_root, paramPath);
    if(!oid_item) {
        vos_err_print("Not exist ParamPath: %s\n", paramPath);
        return NULL;
    }
    if(oid_item->node_type == TR069_OID_ITEM_TYPE_LEAF) {
        VOS_StrnCpy(oid_item->leaf_value->value, paramValue, TR069_OID_SIZE);
        
        int *instanceNums, instanceCount = 0;
        __tr069_tree_obj_count(oid_item, &instanceNums, &instanceCount);
        
        oid_item->leaf_value->set_fn(oid_item, instanceCount?true:false, instanceCount, instanceNums, 
                                     oid_item->leaf_value->set_argc, oid_item->leaf_value->set_argv);

        if(instanceCount)
            free(instanceNums);
        
        return oid_item;
    }
    return NULL;
}


struct tr069_oid *tr069_oid_set_parameter_attributes(rt_rbtree_t oid_root, char paramPath[TR069_OID_SIZE], int Notification)
{
    struct tr069_oid * oid_item = __oid_tree_find_oid_path(oid_root, paramPath);
    if(!oid_item) {
        vos_err_print("Not exist ParamPath: %s\n", paramPath);
        return NULL;
    }
    if(oid_item->node_type == TR069_OID_ITEM_TYPE_LEAF) {
        oid_item->leaf_value->Notification = Notification;
        
        int *instanceNums, instanceCount = 0;
        __tr069_tree_obj_count(oid_item, &instanceNums, &instanceCount);
        
        oid_item->leaf_value->set_fn(oid_item, true, instanceCount, instanceNums, oid_item->leaf_value->set_argc, oid_item->leaf_value->set_argv);

        if(instanceCount)
            free(instanceNums);
        
        return oid_item;
    }
    return NULL;
}



static struct tr069_oid *__tr069_oid_itemdup(struct tr069_oid *from,struct tr069_oid *father)
{
    struct tr069_oid *to = malloc(sizeof(struct tr069_oid));
    VOS_MemZero(to, sizeof(struct tr069_oid));
    
    VOS_Sprintf(to->oidNameItem, "%s", from->oidNameItem);
    to->oidInstanceNum = 0;
    VOS_Sprintf(to->oidAliasNameItem, "%s", from->oidAliasNameItem);

    to->father = father;
    to->oid_type = from->oid_type;
    to->node_type = from->node_type;
    to->writeable = from->writeable;
    
    /* 如果是叶子,需要分配内存 */
    if(from->node_type == TR069_OID_ITEM_TYPE_LEAF) {
        to->leaf_value = malloc(sizeof(struct tr069_oid_leaf));
        VOS_StrnCpy(to->leaf_value->value, from->leaf_value->value, TR069_OID_SIZE);
        to->leaf_value->Notification = from->leaf_value->Notification;
        to->leaf_value->set_fn = from->leaf_value->set_fn;
        to->leaf_value->set_argc = from->leaf_value->set_argc;
        to->leaf_value->set_argv = from->leaf_value->set_argv;
    }
    if(from->oid_type == TR069_OID_TYPE_TABLE) {
        to->obj_operation = malloc(sizeof(struct tr069_oid_obj_opt));
        
        to->obj_operation->add_fn = from->obj_operation->add_fn;
        to->obj_operation->add_argc = from->obj_operation->add_argc;
        to->obj_operation->add_argv = from->obj_operation->add_argv;
        
        to->obj_operation->del_fn = from->obj_operation->del_fn;
        to->obj_operation->del_argc = from->obj_operation->del_argc;
        to->obj_operation->del_argv = from->obj_operation->del_argv;
    }
    __tr069_oid_tree_create(&to->child);

    return to;

}

static void _unused __tr069_oid_tree_clone(struct tr069_oid * from_oid, struct tr069_oid * to_oid)
{
    to_oid->writeable = from_oid->writeable;
    
    struct tr069_oid *from_oid_item = NULL;
    rt_rbtree_node_t *from_node = NULL;
    for(from_node = rt_rbtree_getfirst(from_oid->child); from_node; from_node=rt_rbtree_getnext(from_node)) {
        from_oid_item = from_node->data;
        struct tr069_oid *to_oid_item = __tr069_oid_itemdup(from_oid_item, to_oid);
        rt_rbtree_insert(to_oid->child, to_oid_item, sizeof(struct tr069_oid));
        __tr069_oid_tree_clone(from_oid_item, to_oid_item);
    }
}

_api int tr069_oid_add_object(rt_rbtree_t oid_root, char pathPrefix[TR069_OID_SIZE])
{
    
    struct tr069_oid * oid_item = __oid_tree_find_oid_path(oid_root, pathPrefix);
    if(!oid_item) {
        vos_err_print("Not exist ParamPath: %s\n", pathPrefix);
        return VOS_ERROR;
    }
    if(!oid_item->writeable) {
        vos_err_print("ParamPath: %s is not writeable.\n", pathPrefix);
        return VOS_ERROR;
    }
    struct tr069_oid * template_item = __oid_tree_find_oid_path(oid_item->child, TABLE_NODE);
    if(!template_item) {
        vos_err_print("ParamPath: %s is not addable Object.\n", pathPrefix);
        return VOS_ERROR;
    }

    int oidInstanceNum;
    char aliasName[TR069_OID_ITEM_SIZE];
    
    //获取参数
    int *instanceNums, instanceCount = 0;
    __tr069_tree_obj_count(oid_item, &instanceNums, &instanceCount);

//    vos_info_print("add object. %s, %s\n", oid_item->oidNameItem, template_item->oidNameItem);

    bool add_rlst = false;
    
    if(template_item->obj_operation)
        add_rlst = template_item->obj_operation->add_fn(oid_item, instanceCount+1, instanceCount, instanceNums, 
                                                        template_item->obj_operation->add_argc,
                                                        template_item->obj_operation->add_argv,
                                                        &oidInstanceNum, aliasName);

//    vos_info_print("add object.\n");
    if(instanceCount) free(instanceNums);
    
    if(!add_rlst) {
        vos_err_print("ParamPath: %s add Object failed.\n", pathPrefix);
        return VOS_ERROR;
    }

    /* 实例 */
    struct tr069_oid * instance_item = malloc(sizeof(struct tr069_oid));
    VOS_MemZero(instance_item, sizeof(struct tr069_oid));

    VOS_Sprintf(instance_item->oidNameItem, "%d", oidInstanceNum);
    instance_item->oidInstanceNum = oidInstanceNum;
    VOS_Sprintf(instance_item->oidAliasNameItem, "%s", aliasName);
    instance_item->father = oid_item;

#if 1 //为第一个分配add/delete内存
    instance_item->oid_type = template_item->oid_type;
    instance_item->node_type = template_item->node_type;
    instance_item->writeable = template_item->writeable;
    
    instance_item->obj_operation = malloc(sizeof(struct tr069_oid_obj_opt));
    
    instance_item->obj_operation->add_fn = template_item->obj_operation->add_fn;
    instance_item->obj_operation->add_argc = template_item->obj_operation->add_argc;
    instance_item->obj_operation->add_argv = template_item->obj_operation->add_argv;
    
    instance_item->obj_operation->del_fn = template_item->obj_operation->del_fn;
    instance_item->obj_operation->del_argc = template_item->obj_operation->del_argc;
    instance_item->obj_operation->del_argv = template_item->obj_operation->del_argv;
#endif

    __tr069_oid_tree_create(&instance_item->child);
    
    int ret = rt_rbtree_insert(oid_item->child, instance_item, sizeof(struct tr069_oid));
    if(ret != 0) {
        vos_err_print("ParamPath: %s instance Object %d exist.\n", pathPrefix, oidInstanceNum);
        free(instance_item);
        return VOS_ERROR;
    }
    __tr069_oid_tree_clone(template_item, instance_item);

    return oidInstanceNum;
}

static void __tr069_oid_tree_destroy_loop(rt_rbtree_t tree);


_api int tr069_oid_delete_object(rt_rbtree_t oid_root, char pathPrefix[TR069_OID_SIZE])
{
    struct tr069_oid * instance_item = __oid_tree_find_oid_path(oid_root, pathPrefix);
    if(!instance_item) {
        vos_err_print("Not exist ParamPath: %s\n", pathPrefix);
        return VOS_ERROR;
    }
    if(instance_item->oid_type != TR069_OID_TYPE_TABLE) {
        vos_err_print("ParamPath: %s is not object instance.\n", pathPrefix);
        return VOS_ERROR;
    }
    
    //获取参数
    int *instanceNums, instanceCount = 0;
    __tr069_tree_obj_count(instance_item, &instanceNums, &instanceCount);

    bool del_rlst = false;
    
    if(instance_item->obj_operation)
        del_rlst = instance_item->obj_operation->del_fn(instance_item, instanceCount, instanceNums, 
                                                        instance_item->obj_operation->del_argc,
                                                        instance_item->obj_operation->del_argv);

    if(!del_rlst) {
        vos_err_print("ParamPath: %s delete Object failed.\n", pathPrefix);
        return VOS_ERROR;
    }

    //递归删除子树
    __tr069_oid_tree_destroy_loop(instance_item->child);

    //删除自己在父树种的叶子
    int ret_del = rt_rbtree_delete(instance_item->father->child, instance_item);
    if(ret_del != 0) {
        vos_warning_print("ParamPath: %s delete Object failed.\n", pathPrefix);
        return VOS_ERROR;
    }
    //释放自己的内存
    free(instance_item);

    return VOS_OK;
}



/* 递归销毁树 */
static void __tr069_oid_tree_destroy_loop(rt_rbtree_t tree)
{
    rt_rbtree_t this_tree = tree;
    struct tr069_oid *this_node = NULL;
    rt_rbtree_node_t *find_node = NULL;
    
    for( find_node = rt_rbtree_getfirst(this_tree); find_node; find_node=rt_rbtree_getnext(find_node)) {
        this_node = find_node->data;
        __tr069_oid_tree_destroy_loop(this_node->child);
        rt_rbtree_destroy(this_node->child);
        if(this_node->leaf_value)
            free(this_node->leaf_value);
        if(this_node->obj_operation)
            free(this_node->obj_operation);
        free(this_node);
    }
}

/* 销毁OID树 */
_api void tr069_oid_tree_destroy(rt_rbtree_t oid_root)
{
    __tr069_oid_tree_destroy_loop(oid_root);
    oid_root = NULL;
}

demo.c

#include "cpe_oid_register.h"

static char *OIDs[] = {
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.FrequencyInfoDLSIB.OffsetToPointA",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.FrequencyInfoDLSIB.MultiFrequencyBandListNRSIB.{i}.FreqBandIndicatorNR",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.FrequencyInfoDLSIB.ScsSpecificCarrierList.{i}.SCSSpecificCarrier.OffsetToCarrier",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.FrequencyInfoDLSIB.ScsSpecificCarrierList.{i}.SCSSpecificCarrier.subcarrierSpacing",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.FrequencyInfoDLSIB.ScsSpecificCarrierList.{i}.SCSSpecificCarrier.CarrierBandwidth",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.FrequencyInfoULSIB.AbsoluteFrequencyPointA",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.FrequencyInfoULSIB.ScsSpecificCarrierList.{i}.SCSSpecificCarrier.OffsetToCarrier",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.FrequencyInfoULSIB.ScsSpecificCarrierList.{i}.SCSSpecificCarrier.SubcarrierSpacing",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PHY.FrequencyInfoULSIB.ScsSpecificCarrierList.{i}.SCSSpecificCarrier.CarrierBandwidth",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.SSB.ssbPositionsInBurst.InOneGroup",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.SSB.SsbPeriodicityServingCell",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.SSB.SsPBCHBlockPower",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.SSB.SsbSubcarrierOffset",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.SubCarrierSpacingCommon",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.TddULDLConfigurationCommon.ReferenceSubcarrierSpacing",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.TddULDLConfigurationCommon.pattern1.DlULTransmission",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.TddULDLConfigurationCommon.pattern1.NrofDownlinkSlots",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.TddULDLConfigurationCommon.pattern1.NrofDownlinkSymbols",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.TddULDLConfigurationCommon.pattern1.NrofUplinkSlots",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.TddULDLConfigurationCommon.pattern1.NrofUplinkSymbols",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.TddULDLConfigurationCommon.pattern2.DlULTransmission",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.TddULDLConfigurationCommon.pattern2.NrofDownlinkSlots",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.TddULDLConfigurationCommon.pattern2.NrofDownlinkSymbols",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.TddULDLConfigurationCommon.pattern2.NrofUplinkSlots",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.TddULDLConfigurationCommon.pattern2.NrofUplinkSymbols",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.BWPDL.StartPrbPosition",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.BWPDL.Bandwidth",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.BWPDL.SubcarrierSpacing",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.BWPDL.CyclicPrefix",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.BWPUL.StartPrbPosition",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.BWPUL.Bandwidth",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.BWPUL.SubcarrierSpacing",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.BWPUL.CyclicPrefix",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.BWPUL.TimeAlignmentTimerCommon",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.RACHConfigCommon.RACHConfigGeneric.PrachConfigurationIndex",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.RACHConfigCommon.RACH-ConfigGeneric.Msg1FDM",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.RACH-ConfigCommon.RACH-ConfigGeneric.Msg1FrequencyStart",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.RACHConfigCommon.RACHConfigGeneric.ZeroCorrelationZoneConfig",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PUSCHConfigCommon.GroupHopping",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PUSCHConfigCommon.puschTimeDomainAllocationList.{i}.K2",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PUSCHConfigCommon.puschTimeDomainAllocationList.{i}.MappingType",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PUSCHConfigCommon.puschTimeDomainAllocationList.{i}.StartSymbolAndLength",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PUSCHConfigCommon.Msg3DeltaPreamble",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PUSCHConfigCommon.P0NominalWithGrant",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PUCCHConfigCommon.PucchResourceCommon",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PUCCHConfigCommon.PucchGroupHopping",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PUCCHConfigCommon.HoppingId",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PUCCHConfigCommon.P0nominal",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.RACHConfigCommon.RootType",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.RACHConfigCommon.RootSequenceIndex",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.RACHConfigCommon.Msg1Subcarrier",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.RACHConfigCommon.RestrictedSetConfig",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.DmrsTypeAPosition",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.ControlResourceSetZero",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.SearchSpaceZero",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.SearchSpaceSIB1",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.SearchSpaceOtherSystemInformation",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.PagingSearchSpace",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.RaSearchSpace",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.CommonControlResourceSet.ControlResourceSetId",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.CommonControlResourceSet.FrequencyDomainResources",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.CommonControlResourceSet.Duration",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.commonControlResourceSet.CceRegMappingType",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.CommonControlResourceSet.CceRegMappingType.RegBundleSize",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.CommonControlResourceSet.CceRegMappingType.InterleaverSize",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.CommonControlResourceSet.CceRegMappingType.ShiftIndex",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.CommonControlResourceSet.PrecoderGranularity",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.CommonControlResourceSet.PdcchDMRSScramblingID",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.CommonSearchSpaceList.{i}.SearchSpaceId",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.CommonSearchSpaceList.{i}.ControlResourceSetId",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.CommonSearchSpaceList.{i}.MonitoringSlotPeriodicity",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.CommonSearchSpaceList.MonitoringSlotOffset",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.CommonSearchSpaceList.{i}.Duration",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.CommonSearchSpaceList.{i}.MonitoringSymbolsWithinSlot",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.CommonSearchSpaceList.{i}.nrofCandidates.AggregationLevel1",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.CommonSearchSpaceList.{i}.nrofCandidates.AggregationLevel2",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.CommonSearchSpaceList.{i}.nrofCandidates.AggregationLevel4",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.CommonSearchSpaceList.{i}.nrofCandidates.AggregationLevel8",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.CommonSearchSpaceList.{i}.nrofCandidates.AggregationLevel16",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.CommonSearchSpaceList.{i}.SearchSpaceType",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.CommonSearchSpaceList.{i}.DciFormat00And10En",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.CommonSearchSpaceList.{i}.UeSpecificDciFormats",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDSCH.PDSCHTimeDomainResourceAllocationList.{i}.K0",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDSCH.PDSCHTimeDomainResourceAllocationList.{i}.MappingType",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDSCH.PDSCHTimeDomainResourceAllocationList.{i}.StartSymbolAndLength",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.RACHConfigCommon.TotalNumberOfRAPreambles",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.RACHConfigCommon.SSBPerRACHOccasionChoice",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.RACHConfigCommon.CBPreamblesPerSSB",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.RACH-ConfigCommon.RaMsg3SizeGroupA",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.RACH-ConfigCommon.MessagePowerOffsetGroupB",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.RACHConfigCommon.NumberOfRAPreamblesGroupA",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.RACHConfigCommon.RaContentionResolutionTimer",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.RACHConfigCommon.RsrpThresholdSSB",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.RACH-ConfigCommon.RACH-ConfigGeneric.PreambleReceivedTargetPower",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.RACHConfigCommon.RACHConfigGeneric.PrachConfiguration",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.RACHConfigCommon.RACHConfigGeneric.PowerRampingStep",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.RACH-ConfigCommon.RACH-ConfigGeneric.RaResponseWindow",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.RACHConfigCommon.Msg3TransformPrecoder",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.RRCTimers.T300",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.RRCTimers.T301",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.RRCTimers.T302",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.RRCTimers.T304",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.RRCTimers.T310",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.RRCTimers.T311",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.RRCTimers.T320",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.RRCTimers.N310",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.RRCTimers.N311",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.RRCTimers.T319",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.RRCTimers.T380",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.NeighborList.NRCell.{i}.PLMNID",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.NeighborList.NRCell.{i}.CID",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.NeighborList.NRCell.{i}.NRCarrierARFCN",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.NeighborList.NRCell.{i}.ssbFrequency",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.NeighborList.NRCell.{i}.ssbSubcarrierSpacing",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.NeighborList.NRCell.{i}.PhyCellID",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.NeighborList.NRCell.{i}.TAC",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.NeighborList.NRCell.{i}.Qoffset",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.NeighborList.NRCell.{i}.QRxLevMinOffsetCell",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.NeighborList.NRCell.{i}.QQualMinOffsetCell",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.NeighborList.NRCell.{i}.CIO",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.NeighborList.NRCell.{i}.Blacklisted",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.NeighborList.LTECell.PLMNID.{i}.{i}",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.NeighborList.LTECell.{i}.CID",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.NeighborList.LTECell.{i}.EUTRACarrierARFCN",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.NeighborList.LTECell.{i}.PhyCellID",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.NeighborList.LTECell.{i}.QOffset",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.NeighborList.LTECell.{i}.QRxLevMinOffsetCell",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.NeighborList.LTECell.{i}.QQualMinOffsetCell",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.NeighborList.LTECell.{i}.CIO",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.NeighborList.LTECell.{i}.Blacklisted",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.NeighborList.LTECell.{i}.TAC",
"Device.Services.FAPService.{i}.CellConfig.NR.RAN.NeighborList.LTECell.{i}.EnbType",

"Device.Services.FAPService.{i}.Transport.SCTP.Enable",
"Device.Services.FAPService.{i}.Transport.SCTP.RTOInitial",
"Device.Services.FAPService.{i}.Transport.SCTP.RTOMin",
"Device.Services.FAPService.{i}.Transport.SCTP.RTOMax",
"Device.Services.FAPService.{i}.Transport.SCTP.MaxInitRetransmits",
"Device.Services.FAPService.{i}.Transport.SCTP.HBInterval",
"Device.Services.FAPService.{i}.Transport.SCTP.MaxPathRetransmits",
"Device.Services.FAPService.{i}.Transport.SCTP.MaxAssociationRetransmits",
"Device.Services.FAPService.{i}.Transport.SCTP.ValCookieLife",

"Device.DeviceInfo.ManufacturerOUI",
"Device.DeviceInfo.Manufacturer",
"Device.DeviceInfo.ModelName",
"Device.DeviceInfo.SerialNumber",
"Device.DeviceInfo.HardwareVersion",
"Device.DeviceInfo.SoftwareVersion",
"Device.DeviceInfo.HardwarePlatform",
"Device.DeviceInfo.AdditionalHardwareVersion",
"Device.DeviceInfo.AdditionalSoftwareVersion",
"Device.DeviceInfo.ProvisioningCode",
"Device.DeviceInfo.ProductClass",
"Device.DeviceInfo.UpTime",
"Device.DeviceInfo.3GPPSpecVersion",
"Device.DeviceInfo.FirstUseDate",

"Device.SoftwareCtrl.AutoActivateEnable",
"Device.SoftwareCtrl.ActivateTime",
"Device.SoftwareCtrl.ActivateEnable",
"Device.SoftwareCtrl.SystemCurrentVersion",
"Device.SoftwareCtrl.SystemBackupVersion",

"Device.ManagementServer.URL",
"Device.ManagementServer.Username",
"Device.ManagementServer.Password",
"Device.ManagementServer.PeriodicInformEnable",
"Device.ManagementServer.PeriodicInformTime",
"Device.ManagementServer.PeriodicInformInterval",
"Device.ManagementServer.ParameterKey",
"Device.ManagementServer.ConnectionRequestURL",
"Device.ManagementServer.ConnectionRequestUsername",
"Device.ManagementServer.ConnectionRequestPassword",
"Device.ManagementServer.UDPConnectionRequestAddress",
"Device.ManagementServer.STUNEnable",
"Device.ManagementServer.STUNServerAddress",
"Device.ManagementServer.STUNServerPort",
"Device.ManagementServer.STUNUsername",
"Device.ManagementServer.STUNPassword",
"Device.ManagementServer.STUNMaximumKeepAlivePeriod",
"Device.ManagementServer.STUNMinimumKeepAlivePeriod",
"Device.ManagementServer.NATDetected",

"Device.FaultMgmt.ExpeditedEvent.{i}.PerceivedSeverity",
"Device.FaultMgmt.ExpeditedEvent.{i}.AdditionalText",
"Device.FaultMgmt.ExpeditedEvent.{i}.AdditionalInformation",
"Device.FaultMgmt.QueuedEvent.{i}.SerialNumber",
"Device.FaultMgmt.QueuedEvent.{i}.OUI",
"Device.FaultMgmt.QueuedEvent.{i}.EventTime",
"Device.FaultMgmt.QueuedEvent.{i}.AlarmIdentifier",
"Device.FaultMgmt.QueuedEvent.{i}.NotificationType",
"Device.FaultMgmt.QueuedEvent.{i}.ManagedObjectInstance",
"Device.FaultMgmt.QueuedEvent.{i}.EventType",
"Device.FaultMgmt.QueuedEvent.{i}.ProbableCause",
"Device.FaultMgmt.QueuedEvent.{i}.SpecificProblem",
"Device.FaultMgmt.QueuedEvent.{i}.PerceivedSeverity",
"Device.FaultMgmt.QueuedEvent.{i}.AdditionalText",
"Device.FaultMgmt.QueuedEvent.{i}.AdditionalInformation",

"Device.LogMgmt.PeriodicUploadEnable",
"Device.LogMgmt.URL",
"Device.LogMgmt.Username",
"Device.LogMgmt.Password",
"Device.LogMgmt.PeriodicUploadInterval",

"Device.Ethernet.Interface.{i}.Enable",
"Device.Ethernet.Interface.{i}.Status",
"Device.Ethernet.Interface.{i}.MACAddress",
"Device.Ethernet.Interface.{i}.MaxBitRate",
"Device.Ethernet.Interface.{i}.SignTransMedia",
"Device.Ethernet.Interface.{i}.DuplexMode",

"Device.IP.Interface.{i}.IPv4Address.{i}.IPAddress",
"Device.IP.Interface.{i}.IPv4Address.{i}.DefaultGateway",
"Device.IP.Interface.{i}.IPv4Address.{i}.SubnetMask",
"Device.IP.Interface.{i}.IPv4Address.{i}.AddressingType",
"Device.IP.Interface.{i}.IPv4Address.{i}.PortType",

"Device.IPsec.Enable",
"Device.IPsec.MyKeyMode",
"Device.IPsec.Status",
"Device.IPsec.AHSupported",
"Device.IPsec.IKEv2SupportedEncryptionAlgorithms",
"Device.IPsec.ESPSupportedEncryptionAlgorithms",
"Device.IPsec.IKEv2SupportedPseudoRandomFunctions",
"Device.IPsec.SupportedIntegrityAlgorithms",
"Device.IPsec.SupportedDiffieHellmanGroupTransforms",

NULL,

};

#define NOIDs ({int n=0;while(OIDs[n++]); n-1;})

void oid_display(struct tr069_oid *oid, void *arg)
{
    printf("%s\n", oid->oidNameItem);
}


void oid_set(struct tr069_oid *node, bool isObj, int nObj, int ObjInsNums[], int argc, void *argv[])
{
    
}


bool oid_add(struct tr069_oid *node, int currObjIdx, int nPrevObj, int prevObjInsNums[], int argc, void *argv[], 
                    int *ObjIns, char aliasName[TR069_OID_ITEM_SIZE])
{
    int instance_num = 1;
    *ObjIns = instance_num++;
    
    sprintf(aliasName, "Alias_%d", instance_num-1);
    
    return true;
    
}

bool oid_del(struct tr069_oid *node, int nObj, int ObjInsNums[], int argc, void *argv[])
{
    
    return true;
}


int set_argc = 3;
void *set_argv[] = {
    "Rong","Tao","Sylincom"
};
    
int add_argc = 3;
void *add_argv[] = {
    "Rong","Tao","Sylincom"
}; 
    
int del_argc = 3;
void *del_argv[] = {
    "Rong","Tao","Sylincom"
};

int main()
{
    /* 创建一个树 */
    rt_rbtree_t oid_tree = tr069_oid_tree_create();

    /* 注册树节点:注册了所有节点,各模块视情况而定 */
    int ioid, Noids = NOIDs;
    for(ioid=0;ioid<Noids;ioid++) {
        char defaultV[64] = {0};    //需要一个默认值:字符串
        sprintf(defaultV, "%d", ioid);
        tr069_oid_register(oid_tree, OIDs[ioid], 1, defaultV, ioid%5, 
                            &oid_set, set_argc, set_argv, 
                            &oid_add, add_argc, add_argv, 
                            &oid_del, del_argc, del_argv);
    }

    /* 显示 */
    TR069_OID_GetParamNamesShow(oid_tree, "Device.", 0, printf);

    
    /* 下面以 Device.IP.Interface. 为例,测试该参数树工具接口 */
    TR069_OID_GetParamNamesShow(oid_tree, "Device.IP.Interface.", 0, printf);
    
    /* 添加一个实例 */
    int instanceNum = tr069_oid_add_object(oid_tree, "Device.IP.Interface.");
    printf("Instance Number: %d\n", instanceNum);

    TR069_OID_GetParamNamesShow(oid_tree, "Device.IP.Interface.", 0, printf);

    /* 添加一个二级实例 */
    instanceNum = tr069_oid_add_object(oid_tree, "Device.IP.Interface.1.IPv4Address.");
    printf("Instance Number: %d\n", instanceNum);

    
    TR069_OID_GetParamNamesShow(oid_tree, "Device.IP.Interface.", 0, printf);

    /*********************************************\
     *  参数值操作
    \*********************************************/
    TR069_OID_GetParamValuesShow(oid_tree, "Device.IP.Interface.", printf);

    /* 设置参数 */
    tr069_oid_set_parameter_values(oid_tree, "Device.IP.Interface.1.IPv4Address.1.AddressingType", "MyAddressingType");
    tr069_oid_set_parameter_values(oid_tree, "Device.IP.Interface.1.IPv4Address.1.DefaultGateway", "MyDefaultGateway");
    tr069_oid_set_parameter_values(oid_tree, "Device.IP.Interface.1.IPv4Address.1.IPAddress", "MyIPAddress");
    tr069_oid_set_parameter_values(oid_tree, "Device.IP.Interface.1.IPv4Address.1.PortType", "MyPortType");
    tr069_oid_set_parameter_values(oid_tree, "Device.IP.Interface.1.IPv4Address.1.SubnetMask", "MySubnetMask");

    TR069_OID_GetParamValuesShow(oid_tree, "Device.IP.Interface.", printf);

    /*********************************************\
     *  参数属性操作
    \*********************************************/
    TR069_OID_GetParamAttributeShow(oid_tree, "Device.IP.Interface.", printf);

    /* 设置属性 */
    tr069_oid_set_parameter_attributes(oid_tree, "Device.IP.Interface.1.IPv4Address.1.AddressingType", 1);
    tr069_oid_set_parameter_attributes(oid_tree, "Device.IP.Interface.1.IPv4Address.1.DefaultGateway", 1);
    tr069_oid_set_parameter_attributes(oid_tree, "Device.IP.Interface.1.IPv4Address.1.IPAddress", 1);
    tr069_oid_set_parameter_attributes(oid_tree, "Device.IP.Interface.1.IPv4Address.1.PortType", 1);
    tr069_oid_set_parameter_attributes(oid_tree, "Device.IP.Interface.1.IPv4Address.1.SubnetMask", 1);

    TR069_OID_GetParamAttributeShow(oid_tree, "Device.IP.Interface.", printf);

    /* 删除实例 */
    tr069_oid_delete_object(oid_tree, "Device.IP.Interface.1.IPv4Address.1.");
    tr069_oid_delete_object(oid_tree, "Device.IP.Interface.1.");

    /* 摧毁这个参数树 */
    tr069_oid_tree_destroy(oid_tree);

    return 0;
}

 

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值