Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1671147
  • 博文数量: 124
  • 博客积分: 4078
  • 博客等级: 中校
  • 技术积分: 3943
  • 用 户 组: 普通用户
  • 注册时间: 2010-07-21 11:28
个人简介

新博客:http://sparkandshine.net/

文章分类

全部博文(124)

分类: 嵌入式

2012-07-12 16:52:17

摘要:

    本文讲述了Rime协议栈单跳单播的头部,包括ruc(runicast)、uc(unicast)、broadcast、abc,并用图直观表示。


一、Rime协议栈头部格式

1.1 概述

    Rime协议栈为了能适用不同的网络协议(network protocols),这就需要解决头部格式兼容问题。很容易想到的方法是定义一个统一的头部格式,但缺点几乎是致命的,头部太大且扩展性差。

图1 不同网络协议的头部格式

    巧妙的是,Rime干脆不定义任何头部格式,而是将所有头部字段抽象为类型和长度(结构体packetbuf_attrlist )。将头部各字段组织成数组attributes[],部份源代码如下:

  1. struct packetbuf_attrlist
  2. {
  3.   uint8_t type;
  4.   uint8_t len;
  5. };

  6. static const struct packetbuf_attrlist attributes[] = {...};

    这样的思想很常见,如:HTTP报文整个报文段内容是普通ASCII文本,头部各个字段靠空格或者回车换行符隔开,而Rime头部是用长度来隔开。

1.2 数据包缓冲属性类型

Contiki将数据包缓冲属性类型(packet buffer attribute type)组织成枚举类型变量,如下:

  1. enum
  2. {
  3.   PACKETBUF_ATTR_NONE,
  4.   /* Scope 0 attributes: used only on the local node. */
  5.   PACKETBUF_ATTR_CHANNEL,
  6.   PACKETBUF_ATTR_NETWORK_ID,
  7.   PACKETBUF_ATTR_LINK_QUALITY,
  8.   PACKETBUF_ATTR_RSSI,
  9.   PACKETBUF_ATTR_TIMESTAMP,
  10.   PACKETBUF_ATTR_RADIO_TXPOWER,
  11.   PACKETBUF_ATTR_LISTEN_TIME,
  12.   PACKETBUF_ATTR_TRANSMIT_TIME,
  13.   PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS,
  14.   PACKETBUF_ATTR_MAC_SEQNO,
  15.   PACKETBUF_ATTR_MAC_ACK,
  16.   /* Scope 1 attributes: used between two neighbors only. */
  17.   PACKETBUF_ATTR_RELIABLE,
  18.   PACKETBUF_ATTR_PACKET_ID,
  19.   PACKETBUF_ATTR_PACKET_TYPE,
  20.   PACKETBUF_ATTR_REXMIT,
  21.   PACKETBUF_ATTR_MAX_REXMIT,
  22.   PACKETBUF_ATTR_NUM_REXMIT,
  23.   PACKETBUF_ATTR_PENDING,
  24.   /* Scope 2 attributes: used between end-to-end nodes. */
  25.   PACKETBUF_ATTR_HOPS,
  26.   PACKETBUF_ATTR_TTL,
  27.   PACKETBUF_ATTR_EPACKET_ID,
  28.   PACKETBUF_ATTR_EPACKET_TYPE,
  29.   PACKETBUF_ATTR_ERELIABLE,
  30.   /* These must be last */
  31.   PACKETBUF_ADDR_SENDER,
  32.   PACKETBUF_ADDR_RECEIVER,
  33.   PACKETBUF_ADDR_ESENDER,
  34.   PACKETBUF_ADDR_ERECEIVER,

  35.   PACKETBUF_ATTR_MAX
  36. };

    每个枚举元素都是一个常量(枚举型是预处理指令#define的替代),若第一个枚举元素没有赋值,则默认为0,随后元素以1递增。所以在本例,PACKETBUF_ATTR_NONE为0,PACKETBUF_ATTR_MAX为28。

1.3 runicast头部

在contiki/core/net/rime/runicast.c文件定义了该数组,源代码如下:

  1. static const struct packetbuf_attrlist attributes[] =
  2. {
  3.   RUNICAST_ATTRIBUTES PACKETBUF_ATTR_LAST
  4. };

    RUNICAST_ATTRIBUTES分析见本文第二部分,PACKETBUF_ATTR_LAST分析见本文第四部分。所有宏展开,理清变量间关系,最后得到runicast头部示意图见本文第五部分。


PS:第二、三、四部分系分析过程,无非就是一些宏展开,没多大阅读价值,建立直接看第五部分结论。


二、RUNICAST_ATTRIBUTES

宏RUNICAST_ATTRIBUTES展开如下:

  1. #define RUNICAST_ATTRIBUTES \
  2. { PACKETBUF_ATTR_PACKET_TYPE, PACKETBUF_ATTR_BIT }, \
  3. { PACKETBUF_ATTR_PACKET_ID, PACKETBUF_ATTR_BIT * RUNICAST_PACKET_ID_BITS }, \
  4. STUNICAST_ATTRIBUTES

2.1 PACKETBUF_ATTR_PACKET_TYPE

    PACKETBUF_ATTR_PACKET_TYPE是上述枚举类型的元素,其值为15,PACKETBUF_ATTR_BIT由#define定义,其值为1。

2.2 PACKETBUF_ATTR_PACKET_ID

    PACKETBUF_ATTR_PACKET_ID是上述枚举类型的元素,其值为14。PACKETBUF_ATTR_BIT 、RUNICAST_PACKET_ID_BITS皆由#define定义,其值分别为1、2,两者乘积为2。源码如下:

  1. #define PACKETBUF_ATTR_BIT 1
  2. #define RUNICAST_PACKET_ID_BITS 2

2.3 STUNICAST_ATTRIBUTES

宏STUNICAST_ATTRIBUTES一步步展开如下:

  1. #define STUNICAST_ATTRIBUTES UNICAST_ATTRIBUTES

  2. #define UNICAST_ATTRIBUTES
  3. { PACKETBUF_ADDR_RECEIVER, PACKETBUF_ADDRSIZE }, \
  4. BROADCAST_ATTRIBUTES

2.3.1 PACKETBUF_ADDR_RECEIVER

    PACKETBUF_ADDR_RECEIVER是上述枚举类型的元素,其值为26。宏PACKETBUF_ADDRSIZE 展开如下:

  1. #define PACKETBUF_ADDRSIZE (sizeof(rimeaddr_t) * PACKETBUF_ATTR_BYTE)

  2. typedef union
  3. {
  4.   unsigned char u8[RIMEADDR_SIZE];
  5. } rimeaddr_t;

  6. #define PACKETBUF_ATTR_BYTE 8

    Rime地址长度RIMEADDR_SIZE默认为2,sizeof(rimeaddr_t)为2,所以PACKETBUF_ADDRSIZE为16。可见packetbuf_attrlist成员变量长度len是以bit为单位

2.3.2 BROADCAST_ATTRIBUTES

    见本文第三部分。


三、BROADCAST_ATTRIBUTES

BROADCAST_ATTRIBUTES宏展开如下:

  1. #define BROADCAST_ATTRIBUTES
  2. { PACKETBUF_ADDR_SENDER, PACKETBUF_ADDRSIZE }, \
  3. ABC_ATTRIBUTES

3.1 PACKETBUF_ADDR_SENDER

    PACKETBUF_ADDR_SENDER是上述枚举类型的元素,其值为25,宏PACKETBUF_ADDRSIZE 展开如下:

  1. #define PACKETBUF_ADDRSIZE (sizeof(rimeaddr_t) * PACKETBUF_ATTR_BYTE)

  2. typedef union
  3. {
  4.   unsigned char u8[RIMEADDR_SIZE];
  5. } rimeaddr_t;

  6. #define PACKETBUF_ATTR_BYTE 8

    Rime地址长度RIMEADDR_SIZE默认为2,sizeof(rimeaddr_t)为2,所以PACKETBUF_ADDRSIZE为16。

3.2 ABC_ATTRIBUTES

宏ABC_ATTRIBUTES展开如下:

  1. #define ABC_ATTRIBUTES


四、PACKETBUF_ATTR_LAST

宏PACKETBUF_ATTR_LAST 展开如下:

  1. #define PACKETBUF_ATTR_LAST { PACKETBUF_ATTR_NONE, 0 }

PACKETBUF_ATTR_NONE是上述枚举类型的元素,其值为0。


五、总结

5.1 runicast头部

runicast的attributes数组定义源代码如下:

  1. static const struct packetbuf_attrlist attributes[] =
  2. {
  3.   RUNICAST_ATTRIBUTES
  4.   PACKETBUF_ATTR_LAST
  5. };

结合上述分析,runicast头部示意图如下:

图2 runicast头部示意图

5.2 unicast头部

unicast的attributes数组定义源代码如下:

  1. static const struct packetbuf_attrlist attributes[] =
  2. {
  3.   UNICAST_ATTRIBUTES
  4.   PACKETBUF_ATTR_LAST
  5. };

结合上述分析,runicast头部示意图如下:

图3 unicast头部示意图

5.3 broadcast

的attributes数组定义源代码如下:

  1. static const struct packetbuf_attrlist attributes[] =
  2. {
  3.   BROADCAST_ATTRIBUTES
  4.   PACKETBUF_ATTR_LAST
  5. };

结合上述分析,broadcast头部示意图如下:

图4 broadcast头部示意图

5.4 abc

abc的attributes数组定义源代码如下:

  1. static const struct packetbuf_attrlist attributes[] =
  2. {
  3.   ABC_ATTRIBUTES
  4.   PACKETBUF_ATTR_LAST
  5. };

结合上述分析,abc头部示意图如下:

图5 abc头部示意图

5.5 其他问题

    如果你细心的话,你会发现rucb、stuc、abc是没有头部的。我的理解是这样的,rucb块传输层,直接把应用程序数据交给下层ruc,无须增加头部。Rime协议栈将可靠传输层分成两层stuc与ruc,只须加一次头部。abc层的数据直接发送出去,也无须增加头部(abc类似于物理层的功能)。

本文所有头部示意图源文件 Rime单跳单播头部.rar   


参考资料:

[1] Adam Dunkels,Fredrik Osterlind,Zhitao He. An Adaptive Communication Architecture for Wireless Sensor Networks[J]

阅读(4928) | 评论(0) | 转发(6) |
给主人留下些什么吧!~~