本文讲述了Contiki之Rime协议栈的Rime地址rimeaddr_t
相关细节,包括地址格式、地址相关操作rimeaddr_copy
和rimeaddr_cmp
、两个全局变量rimeaddr_node_addr
和rimeaddr_null
。
1. 概述
无论哪个协议栈,都得解决一个根本问题,如何标识不同的设备,即编址。如计算机网络中,用端口号标识同一台主机不同的进程,用IP地址标识不同的主机,用MAC唯一标识网卡。同样,Rime协议栈也需对不同节点进行标识,其用联合体rimeaddr_t
进行描述。rimeaddr_t
定义如下(在rimeaddr.h
文件):
typedef union
{
unsigned char u8[RIMEADDR_SIZE];
} rimeaddr_t;
Rime协议栈的节点地址格式为%d.%d.%d...
,默认长度为2,即%d.%d
。可以通过配置RIMEADDR_CONF_SIZE
大小来配置节点地址长度,如contiki-2.5\platform\cc2530dk\contiki-conf.h
中将RIMEADDR_CONF_SIZE
设为8。源代码如下:
#ifdef RIMEADDR_CONF_SIZE
#define RIMEADDR_SIZE RIMEADDR_CONF_SIZE
#else
#define RIMEADDR_SIZE 2
#endif
2. 相关操作
对Rime地址rimeaddr_t
操作很简单,拷贝eaddr_copy
(也可以直接理解成赋值),判断两地址是否相等rimeaddr_cmp
,重设当前节点Rime地址rimeaddr_node_addr
的rimeaddr_set_node_addr
。
2.1 rimeaddr_copy
rimeaddr_copy
拷贝将Rime地址从src
拷贝到dest
,源码如下:
void rimeaddr_copy(rimeaddr_t *dest, const rimeaddr_t *src)
{
u8_t i;
for(i = 0; i < RIMEADDR_SIZE; i++)
{
dest->u8[i] = src->u8[i];
}
}
2.2 rimeaddr_cmp
rimeaddr_cmp
用于判断两个Rime地址是不是相同,相同返回非0,不相同则返回0。源码如下:
int rimeaddr_cmp(const rimeaddr_t *addr1, const rimeaddr_t *addr2)
{
u8_t i;
for(i = 0; i < RIMEADDR_SIZE; i++)
{
if(addr1->u8[i] != addr2->u8[i])
{
return 0;
}
}
return 1;
}
2.3 rimeaddr_set_node_addr
rimeaddr_set_node_addr
用于设置当前节点Rime地址rimeaddr_node_addr
,源码如下:
void rimeaddr_set_node_addr(rimeaddr_t *t)
{
rimeaddr_copy(&rimeaddr_node_addr, t);
}
3. 几个全局变量
3.1 rimeaddr_node_addr
节点的Rime地址,可以通过rimeaddr_set_node_addr()函数改变当前节点的Rime地址,即rimeaddr_node_addr。源代码如下:
rimeaddr_t rimeaddr_node_addr;
void rimeaddr_set_node_addr(rimeaddr_t *t)
{
rimeaddr_copy(&rimeaddr_node_addr, t);
}
3.2 rimeaddr_null
先来看下咱们熟悉的TCP/IP协议栈0.0.0.0
地址,其表示整个网络,用于帮助路由表中无法查询的包(即路由表没有指明特定到达条目的主机和目的网络),路由表中无法查询的包都送到全零网络的路由中去[2]。在一些老的软件中,0.0.0.0
作为广播地址使用[3]。
Rime的零地址貌似跟TCP/IP协议栈不同,路由表使用零地址表明该项未使用,没有配置地址的节点默认为零地址。但配置地址的节点如果设成零地址,在与其他节点通信时将会有问题。这点我也没看懂,待后续源码分析求证。另,建立连接时(如rucb_open
),发送方sender
的地址被设成rimeaddr_null
了。rimeaddr_null
注释及定义如下:
/*This variable contains the null Rime address. The null address is used in route tables to indicate that the table entry is unused. Nodes with no configured address has the null address. Nodes with their node address set to the null address will have problems communicating with other nodes.*/
const rimeaddr_t rimeaddr_null;
如果Rime地址长度为2,则rimeaddr_null
为0.0
;若Rime地址长度为8,则rimeaddr_null
为0.0.0.0.0.0.0.0
。源码如下:
#if RIMEADDR_SIZE == 2
const rimeaddr_t rimeaddr_null = { { 0, 0 } };
#else
#if RIMEADDR_SIZE == 8
const rimeaddr_t rimeaddr_null = { { 0, 0, 0, 0, 0, 0, 0, 0 } };
#endif
#endif
这显然有个问题,如果在配置Rime地址长度RIMEADDR_CONF_SIZ
E时,既不是2也不是8(当然,如果不配置则默认为2),那么rimeaddr_null
则没有初始化,即rimeaddr_null
是一个弱符号,对该符号的处理依赖于编译连接器。
参考资料:
[1] Adam Dunkels论文《Poster Abstract: Rime - A Lightweight Layered Communication Stack for Sensor Networks》
[2] 博文《》
[3] 博文《0.0.0.0的IP是什么地址》