[Rime 协议栈] 广播 ibc

概述

广播的英文全称是identified broad cast,简称ibc。广播也是向本节点覆盖范围内的其它节点发送消息,但与匿名广播abc消息不同的是,ibc中携带了本发送节点的节点地址。
相关代码位于contiki/core/net/rime/broadcast.[ch]

相关定义

attributes

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

其中,

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

与匿名广播的属性想比较,多了一个属性,其属性类型为PACKETBUF_ADDR_SENDER,即广播的发送节点的节点地址。其它节点接收到本广播消息后,通过解析包头,查看包属性,就可以知道是由哪个节点发送的消息。

struct broadcast_callbacks

1
2
3
4
5
struct broadcast_callbacks {
/** Called when a packet has been received by the broadcast module. */
void (* recv)(struct broadcast_conn *ptr, const linkaddr_t *sender);
void (* sent)(struct broadcast_conn *ptr, int status, int num_tx);
};

与匿名广播的回调函数结构体完全类似。

struct broadcast_conn

1
2
3
4
struct broadcast_conn {
struct abc_conn c;
const struct broadcast_callbacks *u;
};

与匿名广播的连接定义完全类似,但是它的内部使用了一个匿名广播。我们一直在说,匿名广播是Rime协议栈中其它子协议的基础,从这里就可以看出来。

struct abc_callbacks broadcast

1
static const struct abc_callbacks broadcast = {recv_from_abc, sent_by_abc};

定义了一个匿名广播abc的回调函数结构体。在进行ibc广播时,将用这个结构体中的回调函数作为abc的回调函数。

相关函数

broadcast_open

1
2
3
4
5
6
7
void broadcast_open(struct broadcast_conn *c, uint16_t channel,
const struct broadcast_callbacks *u)
{
abc_open(&c->c, channel, &broadcast);
c->u = u;
channel_set_attributes(channel, attributes);
}

打开一个ibc广播。主要做了以下3件事儿:
第一,打开一个匿名广播abc,并设置abc的回调函数为broadcast中的回调函数
第二,设置ibc的回调函数
第三,设置通道属性

broadcast_close

1
2
3
4
void broadcast_close(struct broadcast_conn *c)
{
abc_close(&c->c);
}

关闭一个ibc广播,其实就是关闭一个匿名广播abc。

broadcast_send

1
2
3
4
5
int broadcast_send(struct broadcast_conn *c)
{
packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &linkaddr_node_addr);
return abc_send(&c->c);
}

发送一个广播消息,主要有两步:
第一,设置地址属性PACKETBUF_ADDR_SENDER,其中linkaddr_node_addr是本节点的节点地址
第二,调用abc的发送函数

sent_by_abc

1
2
3
4
5
6
7
8
9
static void
sent_by_abc(struct abc_conn *bc, int status, int num_tx)
{
struct broadcast_conn *c = (struct broadcast_conn *)bc;

if(c->u->sent) {
c->u->sent(c, status, num_tx);
}
}

recv_from_abc

1
2
3
4
5
6
7
8
9
10
11
static void recv_from_abc(struct abc_conn *bc)
{
linkaddr_t sender;
struct broadcast_conn *c = (struct broadcast_conn *)bc;

linkaddr_copy(&sender, packetbuf_addr(PACKETBUF_ADDR_SENDER));

if(c->u->recv) {
c->u->recv(c, &sender);
}
}

小结

ibc就是在abc的基础之上添加了一个发送地址的包属性,然后调用abc对应的接口。