nbr_table源码之头文件

来源:互联网 发布:开通淘宝直播什么要求 编辑:程序博客网 时间:2024/06/05 14:39
学完contiki的内核之后,想重点学一学路由协议RPL。奈何资料实在太少,网上大部分都讲只是讲个大概而已,很多具体细节都没有,我也是很苦恼。基本上都是靠《基于IP的物联网架构、技术与应用》还有这位博主http://cgbluesky.blog.163.com/里翻译的关于RPL的标准手册RFC6550。艰难学了个基本,接下来更多细节想从RPL的源码里一探究竟,没想到一打开完全懵逼,太复杂了,咱还是一步一步来吧,先从里面经常用到的结构里开始研究。第一个就是邻居列表nbr_table。
如果你有contiki的源码可以在这个目录下\core\net找到nbr_table.h。至于为啥叫邻居列表,那就得去看IPV6了,里面就有这个邻居的概念,我想这个邻居列表可能不仅用在RPL,IPV6的源码里肯定也会用到吧。废话不多说,开始看源码。
/*********************************************************************nbr_table.h***************************************************/
首先定义了一个邻居列表里成员的数量,最多8个成员
/* Neighbor table size */
#ifdef NBR_TABLE_CONF_MAX_NEIGHBORS
#define NBR_TABLE_MAX_NEIGHBORS NBR_TABLE_CONF_MAX_NEIGHBORS
#else /* NBR_TABLE_CONF_MAX_NEIGHBORS */
#define NBR_TABLE_MAX_NEIGHBORS 8
#endif /* NBR_TABLE_CONF_MAX_NEIGHBORS */
邻居列表的成员是什么数据类型的,这里定为void,是为了方便后续邻居成员可以是各种结构体类型
/* An item in a neighbor table */
typedef void nbr_table_item_t;
邻居列表的操作函数,用来从列表里删除成员
/* Callback function, called when removing an item from a table */
typedef void(nbr_table_callback)(nbr_table_item_t *item);
邻居列表结构体,就是说一个列表就是一个结构体咯,结构体里有一个索引index,列表成员的大小item_size,还有用来从列表里删除成员的函数,最后是一个成员指针。你可能觉得很奇怪,不是说是一个列表么,没看出来有多个成员的感觉啊,别急往下看就懂了。
/* A neighbor table */
typedef struct nbr_table {
int index;
int item_size;
nbr_table_callback *callback;
nbr_table_item_t *data;
} nbr_table_t;
重头戏来了,这里定义了一个宏,叫NBR_TABLE(type,name),它就是用来创建一个邻居列表的。这种风格跟contiki系统的源码风格是一样的,一个宏就代表了三条语句。我们注意看这里的两个宏NBR_TABLE和NBR_TABLE_GLOBAL有啥区别,就最后一条语句一个是静态变量一个不是,其实GLOBAL就代表着这个变量是全局的,但是宏里定义的前两个可不是。在rpl源码里我们找一个例子展开来看看。比如NBR_TABLE_GLOBAL(rpl_parent_t, rpl_parents);展开
static rpl_parent_t rpl_parents_mem[8]
static nbr_table_t rpl_parents_struct = {0,sizeof(type),NULL,(nbr_table_item_t *) rpl_parents_mem}
nbr_table_t* rpl_parents = &rpl_parents_struct
是不是就看出来点意思了,首先定义了一个你指定了type的类型的数组,然后定义了一个邻居列表结构体,然后把那个数组的指针交给nbr_table_item_t指针类型的成员,也就是列表结构体里的data成员实际就是列表数组的头指针了,突然明白了为啥要有item_size这个成员了,并且我们也看到了这个成员的值是sizeof(type),也就是以后要一个一个成员取出来的时候就知道一次取多少数据了,这个列表结构体可以适用各种不同类型的成员,真是灵活。
static type
#define NBR_TABLE(type, name) \
static type _##name##_mem[NBR_TABLE_MAX_NEIGHBORS]; \
static nbr_table_t name##_struct = { 0, sizeof(type), NULL, (nbr_table_item_t *)_##name##_mem }; \
static nbr_table_t *name = &name##_struct \

/** \brief A non-static neighbor table. To be initialized through nbr_table_register(name) */
#define NBR_TABLE_GLOBAL(type, name) \
static type _##name##_mem[NBR_TABLE_MAX_NEIGHBORS]; \
static nbr_table_t name##_struct = { 0, sizeof(type), NULL, (nbr_table_item_t *)_##name##_mem }; \
nbr_table_t *name = &name##_struct \
#define NBR_TABLE_DECLARE(name) extern nbr_table_t *name
最后这个列表结构体指针是为了给定义邻居列表结构体之外的模块访问列表结构体的时候使用的,所以就有下面这个宏,对这个列表结构体指针的一个外部声明。像刚刚那个NBR_TABLE_GLOBAL(rpl_parent_t, rpl_parents);是在rpl_dag.c里,而在rpl.h里有NBR_TABLE_DECLARE(rpl_parents);这么一句,所以在rpl.c里很多地方都用到这个rpl_parents指针。
typedef enum {
NBR_TABLE_REASON_UNDEFINED,
NBR_TABLE_REASON_RPL_DIO,
NBR_TABLE_REASON_RPL_DAO,
NBR_TABLE_REASON_RPL_DIS,
NBR_TABLE_REASON_ROUTE,
NBR_TABLE_REASON_IPV6_ND,
NBR_TABLE_REASON_MAC,
NBR_TABLE_REASON_LLSEC
} nbr_table_reason_t;
这个枚举型暂时还不清楚用在哪
接下来就声明了一大堆针对这个邻居列表结构体的操作函数。
int nbr_table_register(nbr_table_t *table, nbr_table_callback *callback);
nbr_table_item_t *nbr_table_head(nbr_table_t *table);
nbr_table_item_t *nbr_table_next(nbr_table_t *table, nbr_table_item_t *item);
nbr_table_item_t *nbr_table_add_lladdr(nbr_table_t *table, const linkaddr_t *lladdr, nbr_table_reason_t reason, void *data);
nbr_table_item_t *nbr_table_get_from_lladdr(nbr_table_t *table, const linkaddr_t *lladdr);
int nbr_table_remove(nbr_table_t *table, nbr_table_item_t *item);
int nbr_table_lock(nbr_table_t *table, nbr_table_item_t *item);
int nbr_table_unlock(nbr_table_t *table, nbr_table_item_t *item);
linkaddr_t *nbr_table_get_lladdr(nbr_table_t *table, const nbr_table_item_t *item);
#endif /* NBR_TABLE_H_ */