rpl: request DODAG_CONF and PREFIX_INFO option from parent when joining a DODAG
This commit is contained in:
parent
775a85565b
commit
f4660e8ff5
@ -235,7 +235,8 @@ struct gnrc_rpl_dodag {
|
||||
uint8_t dao_seq; /**< dao sequence number */
|
||||
uint8_t dao_counter; /**< amount of retried DAOs */
|
||||
bool dao_ack_received; /**< flag to check for DAO-ACK */
|
||||
uint8_t dodag_conf_counter; /**< limitation of the sending of DODAG_CONF options */
|
||||
bool dodag_conf_requested; /**< flag to send DODAG_CONF options */
|
||||
bool prefix_info_requested; /**< flag to send PREFIX_INFO options */
|
||||
msg_t dao_msg; /**< msg_t for firing a dao */
|
||||
uint64_t dao_time; /**< time to schedule the next DAO */
|
||||
xtimer_t dao_timer; /**< timer to schedule the next DAO */
|
||||
|
||||
@ -94,6 +94,8 @@ gnrc_rpl_dodag_t *gnrc_rpl_root_init(uint8_t instance_id, ipv6_addr_t *dodag_id)
|
||||
dodag->grounded = GNRC_RPL_GROUNDED;
|
||||
dodag->node_status = GNRC_RPL_ROOT_NODE;
|
||||
dodag->my_rank = GNRC_RPL_ROOT_RANK;
|
||||
dodag->dodag_conf_requested = true;
|
||||
dodag->prefix_info_requested = true;
|
||||
|
||||
trickle_start(gnrc_rpl_pid, &dodag->trickle, GNRC_RPL_MSG_TYPE_TRICKLE_INTERVAL,
|
||||
GNRC_RPL_MSG_TYPE_TRICKLE_CALLBACK, (1 << dodag->dio_min),
|
||||
|
||||
@ -101,8 +101,11 @@ void gnrc_rpl_send_DIO(gnrc_rpl_dodag_t *dodag, ipv6_addr_t *destination)
|
||||
uint8_t *pos;
|
||||
int size = sizeof(icmpv6_hdr_t) + sizeof(gnrc_rpl_dio_t);
|
||||
|
||||
if ((dodag->dodag_conf_counter % 3) == 0) {
|
||||
if (dodag->dodag_conf_requested) {
|
||||
size += sizeof(gnrc_rpl_opt_dodag_conf_t);
|
||||
}
|
||||
|
||||
if (dodag->prefix_info_requested) {
|
||||
size += sizeof(gnrc_rpl_opt_prefix_info_t);
|
||||
}
|
||||
|
||||
@ -126,7 +129,7 @@ void gnrc_rpl_send_DIO(gnrc_rpl_dodag_t *dodag, ipv6_addr_t *destination)
|
||||
|
||||
pos += sizeof(*dio);
|
||||
|
||||
if ((dodag->dodag_conf_counter % 3) == 0) {
|
||||
if (dodag->dodag_conf_requested) {
|
||||
gnrc_rpl_opt_dodag_conf_t *dodag_conf;
|
||||
dodag_conf = (gnrc_rpl_opt_dodag_conf_t *) pos;
|
||||
dodag_conf->type = GNRC_RPL_OPT_DODAG_CONF;
|
||||
@ -142,7 +145,10 @@ void gnrc_rpl_send_DIO(gnrc_rpl_dodag_t *dodag, ipv6_addr_t *destination)
|
||||
dodag_conf->default_lifetime = dodag->default_lifetime;
|
||||
dodag_conf->lifetime_unit = byteorder_htons(dodag->lifetime_unit);
|
||||
pos += sizeof(*dodag_conf);
|
||||
dodag->dodag_conf_requested = false;
|
||||
}
|
||||
|
||||
if (dodag->prefix_info_requested) {
|
||||
gnrc_rpl_opt_prefix_info_t *prefix_info;
|
||||
prefix_info = (gnrc_rpl_opt_prefix_info_t *) pos;
|
||||
prefix_info->type = GNRC_RPL_OPT_PREFIX_INFO;
|
||||
@ -156,15 +162,14 @@ void gnrc_rpl_send_DIO(gnrc_rpl_dodag_t *dodag, ipv6_addr_t *destination)
|
||||
|
||||
memset(&prefix_info->prefix, 0, sizeof(prefix_info->prefix));
|
||||
ipv6_addr_init_prefix(&prefix_info->prefix, &dodag->dodag_id, dodag->prefix_len);
|
||||
dodag->prefix_info_requested = false;
|
||||
}
|
||||
|
||||
dodag->dodag_conf_counter++;
|
||||
gnrc_rpl_send(pkt, NULL, destination, &dodag->dodag_id);
|
||||
}
|
||||
|
||||
void gnrc_rpl_send_DIS(gnrc_rpl_dodag_t *dodag, ipv6_addr_t *destination)
|
||||
{
|
||||
(void) dodag;
|
||||
gnrc_pktsnip_t *pkt;
|
||||
icmpv6_hdr_t *icmp;
|
||||
gnrc_rpl_dis_t *dis;
|
||||
@ -227,7 +232,8 @@ void gnrc_rpl_recv_DIS(gnrc_rpl_dis_t *dis, ipv6_addr_t *src, ipv6_addr_t *dst,
|
||||
else {
|
||||
for (uint8_t i = 0; i < GNRC_RPL_DODAGS_NUMOF; ++i) {
|
||||
if (gnrc_rpl_dodags[i].state != 0) {
|
||||
gnrc_rpl_dodags[i].dodag_conf_counter = 0;
|
||||
gnrc_rpl_dodags[i].dodag_conf_requested = true;
|
||||
gnrc_rpl_dodags[i].prefix_info_requested = true;
|
||||
gnrc_rpl_send_DIO(&gnrc_rpl_dodags[i], src);
|
||||
}
|
||||
}
|
||||
@ -322,12 +328,13 @@ static bool _gnrc_rpl_check_options_validity(int msg_type, gnrc_rpl_dodag_t *dod
|
||||
|
||||
/** @todo allow target prefixes in target options to be of variable length */
|
||||
bool _parse_options(int msg_type, gnrc_rpl_dodag_t *dodag, gnrc_rpl_opt_t *opt, uint16_t len,
|
||||
ipv6_addr_t *src)
|
||||
ipv6_addr_t *src, uint32_t *included_opts)
|
||||
{
|
||||
uint16_t l = 0;
|
||||
gnrc_rpl_opt_target_t *first_target = NULL;
|
||||
eui64_t iid;
|
||||
kernel_pid_t if_id = KERNEL_PID_UNDEF;
|
||||
*included_opts = 0;
|
||||
|
||||
if (!_gnrc_rpl_check_options_validity(msg_type, dodag, opt, len)) {
|
||||
return false;
|
||||
@ -337,16 +344,20 @@ bool _parse_options(int msg_type, gnrc_rpl_dodag_t *dodag, gnrc_rpl_opt_t *opt,
|
||||
switch(opt->type) {
|
||||
case (GNRC_RPL_OPT_PAD1):
|
||||
DEBUG("RPL: PAD1 option parsed\n");
|
||||
*included_opts |= ((uint32_t) 1) << GNRC_RPL_OPT_PAD1;
|
||||
l += 1;
|
||||
opt = (gnrc_rpl_opt_t *) (((uint8_t *) opt) + 1);
|
||||
continue;
|
||||
|
||||
case (GNRC_RPL_OPT_PADN):
|
||||
DEBUG("RPL: PADN option parsed\n");
|
||||
*included_opts |= ((uint32_t) 1) << GNRC_RPL_OPT_PADN;
|
||||
break;
|
||||
|
||||
case (GNRC_RPL_OPT_DODAG_CONF):
|
||||
DEBUG("RPL: DODAG CONF DIO option parsed\n");
|
||||
*included_opts |= ((uint32_t) 1) << GNRC_RPL_OPT_DODAG_CONF;
|
||||
dodag->dodag_conf_requested = true;
|
||||
gnrc_rpl_opt_dodag_conf_t *dc = (gnrc_rpl_opt_dodag_conf_t *) opt;
|
||||
gnrc_rpl_of_t *of = gnrc_rpl_get_of_for_ocp(byteorder_ntohs(dc->ocp));
|
||||
if (of != NULL) {
|
||||
@ -370,6 +381,8 @@ bool _parse_options(int msg_type, gnrc_rpl_dodag_t *dodag, gnrc_rpl_opt_t *opt,
|
||||
|
||||
case (GNRC_RPL_OPT_PREFIX_INFO):
|
||||
DEBUG("RPL: Prefix Information DIO option parsed\n");
|
||||
*included_opts |= ((uint32_t) 1) << GNRC_RPL_OPT_PREFIX_INFO;
|
||||
dodag->prefix_info_requested = true;
|
||||
gnrc_rpl_opt_prefix_info_t *pi = (gnrc_rpl_opt_prefix_info_t *) opt;
|
||||
ipv6_addr_t all_RPL_nodes = GNRC_RPL_ALL_NODES_ADDR;
|
||||
if_id = gnrc_ipv6_netif_find_by_addr(NULL, &all_RPL_nodes);
|
||||
@ -385,6 +398,7 @@ bool _parse_options(int msg_type, gnrc_rpl_dodag_t *dodag, gnrc_rpl_opt_t *opt,
|
||||
|
||||
case (GNRC_RPL_OPT_TARGET):
|
||||
DEBUG("RPL: RPL TARGET DAO option parsed\n");
|
||||
*included_opts |= ((uint32_t) 1) << GNRC_RPL_OPT_TARGET;
|
||||
if_id = gnrc_ipv6_netif_find_by_prefix(NULL, &dodag->dodag_id);
|
||||
if (if_id == KERNEL_PID_UNDEF) {
|
||||
DEBUG("RPL: no interface found for the configured DODAG id\n");
|
||||
@ -405,6 +419,7 @@ bool _parse_options(int msg_type, gnrc_rpl_dodag_t *dodag, gnrc_rpl_opt_t *opt,
|
||||
|
||||
case (GNRC_RPL_OPT_TRANSIT):
|
||||
DEBUG("RPL: RPL TRANSIT INFO DAO option parsed\n");
|
||||
*included_opts |= ((uint32_t) 1) << GNRC_RPL_OPT_TRANSIT;
|
||||
gnrc_rpl_opt_transit_t *transit = (gnrc_rpl_opt_transit_t *) opt;
|
||||
if (first_target == NULL) {
|
||||
DEBUG("RPL: Encountered a RPL TRANSIT DAO option without \
|
||||
@ -475,9 +490,6 @@ void gnrc_rpl_recv_DIO(gnrc_rpl_dio_t *dio, ipv6_addr_t *src, uint16_t len)
|
||||
}
|
||||
|
||||
if (gnrc_rpl_dodag_add(inst, &dio->dodag_id, &dodag)) {
|
||||
DEBUG("RPL: Joined DODAG (%s).\n",
|
||||
ipv6_addr_to_str(addr_str, &dio->dodag_id, sizeof(addr_str)));
|
||||
|
||||
gnrc_rpl_parent_t *parent = NULL;
|
||||
|
||||
if (!gnrc_rpl_parent_add_by_addr(dodag, src, &parent) && (parent == NULL)) {
|
||||
@ -490,18 +502,29 @@ void gnrc_rpl_recv_DIO(gnrc_rpl_dio_t *dio, ipv6_addr_t *src, uint16_t len)
|
||||
|
||||
parent->rank = byteorder_ntohs(dio->rank);
|
||||
|
||||
if(!_parse_options(GNRC_RPL_ICMPV6_CODE_DIO, dodag, (gnrc_rpl_opt_t *)(dio + 1), len, NULL)) {
|
||||
uint32_t included_opts = 0;
|
||||
if(!_parse_options(GNRC_RPL_ICMPV6_CODE_DIO, dodag, (gnrc_rpl_opt_t *)(dio + 1), len, NULL,
|
||||
&included_opts)) {
|
||||
DEBUG("RPL: Error encountered during DIO option parsing - remove DODAG\n");
|
||||
gnrc_rpl_dodag_remove(dodag);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(included_opts & (((uint32_t) 1) << GNRC_RPL_OPT_DODAG_CONF))) {
|
||||
DEBUG("RPL: DIO without DODAG_CONF option - remove DODAG and request new DIO\n");
|
||||
gnrc_rpl_dodag_remove(dodag);
|
||||
gnrc_rpl_send_DIS(NULL, src);
|
||||
return;
|
||||
}
|
||||
|
||||
gnrc_rpl_delay_dao(dodag);
|
||||
trickle_start(gnrc_rpl_pid, &dodag->trickle, GNRC_RPL_MSG_TYPE_TRICKLE_INTERVAL,
|
||||
GNRC_RPL_MSG_TYPE_TRICKLE_CALLBACK, (1 << dodag->dio_min),
|
||||
dodag->dio_interval_doubl, dodag->dio_redun);
|
||||
|
||||
gnrc_rpl_parent_update(dodag, parent);
|
||||
DEBUG("RPL: Joined DODAG (%s).\n",
|
||||
ipv6_addr_to_str(addr_str, &dio->dodag_id, sizeof(addr_str)));
|
||||
return;
|
||||
}
|
||||
else if (dodag == NULL) {
|
||||
@ -581,8 +604,9 @@ void gnrc_rpl_recv_DIO(gnrc_rpl_dio_t *dio, ipv6_addr_t *src, uint16_t len)
|
||||
parent->dtsn = dio->dtsn;
|
||||
dodag->grounded = dio->g_mop_prf >> GNRC_RPL_GROUNDED_SHIFT;
|
||||
dodag->prf = dio->g_mop_prf & GNRC_RPL_PRF_MASK;
|
||||
if(!_parse_options(GNRC_RPL_ICMPV6_CODE_DIO, dodag,
|
||||
(gnrc_rpl_opt_t *)(dio + 1), len, NULL)) {
|
||||
uint32_t included_opts = 0;
|
||||
if(!_parse_options(GNRC_RPL_ICMPV6_CODE_DIO, dodag, (gnrc_rpl_opt_t *)(dio + 1), len, NULL,
|
||||
&included_opts)) {
|
||||
DEBUG("RPL: Error encountered during DIO option parsing - remove DODAG\n");
|
||||
gnrc_rpl_dodag_remove(dodag);
|
||||
return;
|
||||
@ -800,7 +824,8 @@ void gnrc_rpl_recv_DAO(gnrc_rpl_dao_t *dao, ipv6_addr_t *src, uint16_t len)
|
||||
}
|
||||
}
|
||||
|
||||
if(!_parse_options(GNRC_RPL_ICMPV6_CODE_DAO, dodag, opts, len, src)) {
|
||||
uint32_t included_opts = 0;
|
||||
if(!_parse_options(GNRC_RPL_ICMPV6_CODE_DAO, dodag, opts, len, src, &included_opts)) {
|
||||
DEBUG("RPL: Error encountered during DAO option parsing - ignore DAO\n");
|
||||
return;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user