您的位置:首页 > 运维架构

Rime协议学习笔记:(十四)multihop多跳传输

2017-03-29 22:02 691 查看

十四.multihop多跳传输

  multihop源码文件:contiki-3.0/core/net/rime/multihop.[c/h]

multihop模块实现了多跳转发机制。使用multihop之前,必须已经用route_add函数建立了路由,路由的建立还使用到另一Rime模块route-discovery。multihop模块利用网络中每个节点的多跳转发功能将数据包发送给指定节点。应用或协议通过使用多跳原语来为选择下一跳邻居提供路由功能。如果multihop原语在发送数据包的过程中没找到合适的下一跳邻居,调用者会立即通告并可能选择发起一个路由选择进程。

14.1 multihop相关定义

  multihop相关结构体:

struct multihop_conn {
/**多跳连接,建立在单跳单播基础上*/
struct unicast_conn c;
const struct multihop_callbacks *cb;
};

struct multihop_callbacks {
/**用户自定义回调结构体*/
void (* recv)(struct multihop_conn *ptr,
const linkaddr_t *sender,
const linkaddr_t *prevhop,
uint8_t hops);
linkaddr_t *(* forward)(struct multihop_conn *ptr,
const linkaddr_t *originator,
const linkaddr_t *dest,
const linkaddr_t *prevhop,
uint8_t hops);
};


  multihop数据包相关属性:

/**multihop.c中的定义*/
static const struct packetbuf_attrlist attributes[] = {MULTIHOP_ATTRIBUTES  PACKETBUF_ATTR_LAST};

/**multihop.h中的定义*/
#define MULTIHOP_ATTRIBUTES   { PACKETBUF_ADDR_ESENDER, PACKETBUF_ADDRSIZE }, \
{ PACKETBUF_ADDR_ERECEIVER, PACKETBUF_ADDRSIZE }, \
{ PACKETBUF_ATTR_HOPS, PACKETBUF_ATTR_BIT * 5 }, \
UNICAST_ATTRIBUTES
//在unicast数据包的基础上增加了发送者地址、指定接收者地址、跳数属性


14.2 主要操作

14.2.1 回调函数

  (1)用户自定义回调函数:由用户在使用multihop时自己定义并调用,调用时封装在multihop_callbacks里。

  (2)系统回调函数为:unicast_callbacks,只定义接收回调函数。具体代码如下:

static const struct unicast_callbacks data_callbacks = { data_packet_received };

void data_packet_received(struct unicast_conn *uc, const linkaddr_t *from){
/**系统接收回调函数,处理收到的数据包,分为中间节点和指定接收节点两种情况*/
struct multihop_conn *c = (struct multihop_conn *)uc;
linkaddr_t *nexthop;
linkaddr_t sender, receiver;

//拷贝数据包属性,避免因应用程序自身需要而将数据包属性重写或清除
linkaddr_copy(&sender, packetbuf_addr(PACKETBUF_ADDR_ESENDER));
linkaddr_copy(&receiver, packetbuf_addr(PACKETBUF_ADDR_ERECEIVER));
//打印收到数据包的信息
PRINTF("data_packet_received from %d.%d towards %d.%d len %d\n",
from
aecb
->u8[0], from->u8[1],
packetbuf_addr(PACKETBUF_ADDR_ERECEIVER)->u8[0],
packetbuf_addr(PACKETBUF_ADDR_ERECEIVER)->u8[1],
packetbuf_datalen());

/*如果本节点地址和指定接收者地址相同,即数据包已到达指定接收者*/
if(linkaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_ERECEIVER), &linkaddr_node_addr)) {
PRINTF("for us!\n");
if(c->cb->recv) { //调用用户自定义接收回调
c->cb->recv(c, &sender, from, packetbuf_attr(PACKETBUF_ATTR_HOPS));
}
}
/*数据包还在中间转发节点*/
else {
nexthop = NULL;
if(c->cb->forward) {
packetbuf_set_attr(PACKETBUF_ATTR_HOPS,
packetbuf_attr(PACKETBUF_ATTR_HOPS) + 1); //将属性跳数加1
nexthop = c->cb->forward(c, &sender, &receiver,
from, packetbuf_attr(PACKETBUF_ATTR_HOPS) - 1); //调用用户自定义forward回调
}
if(nexthop) {
PRINTF("forwarding to %d.%d\n", nexthop->u8[0], nexthop->u8[1]);
unicast_send(&c->c, nexthop); //调用unicast_send转发数据包
}
}
}


14.2.2 multihop_open

void multihop_open(struct multihop_conn *c, uint16_t channel,
const struct multihop_callbacks *callbacks)
{
unicast_open(&c->c, channel, &data_callbacks);
channel_set_attributes(channel, attributes);
c->cb = callbacks;
}


14.2.3 multihop_close

void multihop_close(struct multihop_conn *c){
unicast_close(&c->c);
}


14.2.4 multihop_send

int multihop_send(struct multihop_conn *c, const linkaddr_t *to){
/**用于发送节点发送数据,发送前先调用用户自定义的forward回调获取下一跳的地址*/
linkaddr_t *nexthop;

if(c->cb->forward == NULL) {
return 0;
}
packetbuf_compact(); //压缩包属性
packetbuf_set_addr(PACKETBUF_ADDR_ERECEIVER, to); //将指定的接收者地址压入包属性
packetbuf_set_addr(PACKETBUF_ADDR_ESENDER, &linkaddr_node_addr); //将发送者地址压入包属性
packetbuf_set_attr(PACKETBUF_ATTR_HOPS, 1); //设置属性跳数为1(初始化)
nexthop = c->cb->forward(c, &linkaddr_node_addr, to, NULL, 0); //获取下一跳的地址

if(nexthop == NULL) {
PRINTF("multihop_send: no route\n");
return 0;
}
else {
PRINTF("multihop_send: sending data towards %d.%d\n",nexthop->u8[0], nexthop->u8[1]);
unicast_send(&c->c, nexthop); //调用unicast_send向下一跳发送数据
return 1;
}
}


14.2.5 multihop_resend

void multihop_resend(struct multihop_conn *c, const linkaddr_t *nexthop){
/**重发数据,被mesh模块调用*/
unicast_send(&c->c, nexthop);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: