Merge pull request #692 from simonduq/contrib/rpl-schedule-dao

RPL-Lite: rework DAO sending/resending/refreshing logic
This commit is contained in:
Simon Duquennoy 2019-02-25 22:04:43 +01:00 committed by GitHub
commit a0d94b62a8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 53 additions and 46 deletions

View File

@ -104,7 +104,7 @@ rpl_dag_leave(void)
/* Issue a no-path DAO */ /* Issue a no-path DAO */
if(!rpl_dag_root_is_root()) { if(!rpl_dag_root_is_root()) {
RPL_LOLLIPOP_INCREMENT(curr_instance.dag.dao_curr_seqno); RPL_LOLLIPOP_INCREMENT(curr_instance.dag.dao_last_seqno);
rpl_icmp6_dao_output(0); rpl_icmp6_dao_output(0);
} }
@ -507,7 +507,7 @@ init_dag(uint8_t instance_id, uip_ipaddr_t *dag_id, rpl_ocp_t ocp,
curr_instance.dag.lowest_rank = RPL_INFINITE_RANK; curr_instance.dag.lowest_rank = RPL_INFINITE_RANK;
curr_instance.dag.dao_last_seqno = RPL_LOLLIPOP_INIT; curr_instance.dag.dao_last_seqno = RPL_LOLLIPOP_INIT;
curr_instance.dag.dao_last_acked_seqno = RPL_LOLLIPOP_INIT; curr_instance.dag.dao_last_acked_seqno = RPL_LOLLIPOP_INIT;
curr_instance.dag.dao_curr_seqno = RPL_LOLLIPOP_INIT; curr_instance.dag.dao_last_seqno = RPL_LOLLIPOP_INIT;
memcpy(&curr_instance.dag.dag_id, dag_id, sizeof(curr_instance.dag.dag_id)); memcpy(&curr_instance.dag.dag_id, dag_id, sizeof(curr_instance.dag.dag_id));
return 1; return 1;
@ -657,6 +657,8 @@ rpl_process_dao_ack(uint8_t sequence, uint8_t status)
curr_instance.dag.state = DAG_REACHABLE; curr_instance.dag.state = DAG_REACHABLE;
rpl_timers_dio_reset("Reachable"); rpl_timers_dio_reset("Reachable");
} }
/* Let the rpl-timers module know that we got an ACK for the last DAO */
rpl_timers_notify_dao_ack();
if(!status_ok) { if(!status_ok) {
/* We got a NACK, start poisoning and leave */ /* We got a NACK, start poisoning and leave */

View File

@ -579,7 +579,7 @@ rpl_icmp6_dao_output(uint8_t lifetime)
#endif /* RPL_WITH_DAO_ACK */ #endif /* RPL_WITH_DAO_ACK */
++pos; ++pos;
buffer[pos++] = 0; /* reserved */ buffer[pos++] = 0; /* reserved */
buffer[pos++] = curr_instance.dag.dao_curr_seqno; buffer[pos++] = curr_instance.dag.dao_last_seqno;
/* create target subopt */ /* create target subopt */
prefixlen = sizeof(*prefix) * CHAR_BIT; prefixlen = sizeof(*prefix) * CHAR_BIT;
@ -606,7 +606,7 @@ rpl_icmp6_dao_output(uint8_t lifetime)
LOG_INFO("sending a %sDAO seqno %u, tx count %u, lifetime %u, prefix ", LOG_INFO("sending a %sDAO seqno %u, tx count %u, lifetime %u, prefix ",
lifetime == 0 ? "No-path " : "", lifetime == 0 ? "No-path " : "",
curr_instance.dag.dao_curr_seqno, curr_instance.dag.dao_transmissions, lifetime); curr_instance.dag.dao_last_seqno, curr_instance.dag.dao_transmissions, lifetime);
LOG_INFO_6ADDR(prefix); LOG_INFO_6ADDR(prefix);
LOG_INFO_(" to "); LOG_INFO_(" to ");
LOG_INFO_6ADDR(&curr_instance.dag.dag_id); LOG_INFO_6ADDR(&curr_instance.dag.dag_id);
@ -640,7 +640,7 @@ dao_ack_input(void)
LOG_INFO("received a DAO-%s with seqno %d (%d %d) and status %d from ", LOG_INFO("received a DAO-%s with seqno %d (%d %d) and status %d from ",
status < RPL_DAO_ACK_UNABLE_TO_ACCEPT ? "ACK" : "NACK", sequence, status < RPL_DAO_ACK_UNABLE_TO_ACCEPT ? "ACK" : "NACK", sequence,
curr_instance.dag.dao_curr_seqno, curr_instance.dag.dao_curr_seqno, status); curr_instance.dag.dao_last_seqno, curr_instance.dag.dao_last_seqno, status);
LOG_INFO_6ADDR(&UIP_IP_BUF->srcipaddr); LOG_INFO_6ADDR(&UIP_IP_BUF->srcipaddr);
LOG_INFO_("\n"); LOG_INFO_("\n");

View File

@ -71,8 +71,9 @@ clock_time_t RPL_PROBING_DELAY_FUNC(void);
static void handle_dis_timer(void *ptr); static void handle_dis_timer(void *ptr);
static void handle_dio_timer(void *ptr); static void handle_dio_timer(void *ptr);
static void handle_unicast_dio_timer(void *ptr); static void handle_unicast_dio_timer(void *ptr);
static void handle_dao_timer(void *ptr); static void send_new_dao(void *ptr);
#if RPL_WITH_DAO_ACK #if RPL_WITH_DAO_ACK
static void resend_dao(void *ptr);
static void handle_dao_ack_timer(void *ptr); static void handle_dao_ack_timer(void *ptr);
#endif /* RPL_WITH_DAO_ACK */ #endif /* RPL_WITH_DAO_ACK */
#if RPL_WITH_PROBING #if RPL_WITH_PROBING
@ -224,7 +225,7 @@ static void
schedule_dao_retransmission(void) schedule_dao_retransmission(void)
{ {
clock_time_t expiration_time = RPL_DAO_RETRANSMISSION_TIMEOUT / 2 + (random_rand() % (RPL_DAO_RETRANSMISSION_TIMEOUT)); clock_time_t expiration_time = RPL_DAO_RETRANSMISSION_TIMEOUT / 2 + (random_rand() % (RPL_DAO_RETRANSMISSION_TIMEOUT));
ctimer_set(&curr_instance.dag.dao_timer, expiration_time, handle_dao_timer, NULL); ctimer_set(&curr_instance.dag.dao_timer, expiration_time, resend_dao, NULL);
} }
#endif /* RPL_WITH_DAO_ACK */ #endif /* RPL_WITH_DAO_ACK */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
@ -247,9 +248,8 @@ schedule_dao_refresh(void)
target_refresh -= safety_margin; target_refresh -= safety_margin;
} }
/* Increment next sequno */ /* Schedule transmission */
RPL_LOLLIPOP_INCREMENT(curr_instance.dag.dao_curr_seqno); ctimer_set(&curr_instance.dag.dao_timer, target_refresh, send_new_dao, NULL);
ctimer_set(&curr_instance.dag.dao_timer, target_refresh, handle_dao_timer, NULL);
} }
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
@ -261,36 +261,16 @@ rpl_timers_schedule_dao(void)
* only serves storing mode. Use simple delay instead, with the only purpose * only serves storing mode. Use simple delay instead, with the only purpose
* to reduce congestion. */ * to reduce congestion. */
clock_time_t expiration_time = RPL_DAO_DELAY / 2 + (random_rand() % (RPL_DAO_DELAY)); clock_time_t expiration_time = RPL_DAO_DELAY / 2 + (random_rand() % (RPL_DAO_DELAY));
/* Increment next seqno */ ctimer_set(&curr_instance.dag.dao_timer, expiration_time, send_new_dao, NULL);
RPL_LOLLIPOP_INCREMENT(curr_instance.dag.dao_curr_seqno);
ctimer_set(&curr_instance.dag.dao_timer, expiration_time, handle_dao_timer, NULL);
} }
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static void static void
handle_dao_timer(void *ptr) send_new_dao(void *ptr)
{ {
#if RPL_WITH_DAO_ACK #if RPL_WITH_DAO_ACK
if(rpl_lollipop_greater_than(curr_instance.dag.dao_curr_seqno, /* We are sending a new DAO here. Prepare retransmissions */
curr_instance.dag.dao_last_seqno)) { curr_instance.dag.dao_transmissions = 1;
/* We are sending a new DAO here. Prepare retransmissions */
curr_instance.dag.dao_transmissions = 0;
} else {
/* We are called for the same DAO again */
if(curr_instance.dag.dao_last_acked_seqno == curr_instance.dag.dao_last_seqno) {
/* The last seqno sent is ACKed! Schedule refresh to avoid route expiration */
schedule_dao_refresh();
return;
}
/* We need to re-send the last DAO */
if(curr_instance.dag.dao_transmissions >= RPL_DAO_MAX_RETRANSMISSIONS) {
/* No more retransmissions. Perform local repair and hope to find another . */
rpl_local_repair("DAO max rtx");
return;
}
}
/* Increment transmission counter before sending */
curr_instance.dag.dao_transmissions++;
/* Schedule next retransmission */ /* Schedule next retransmission */
schedule_dao_retransmission(); schedule_dao_retransmission();
#else /* RPL_WITH_DAO_ACK */ #else /* RPL_WITH_DAO_ACK */
@ -299,19 +279,14 @@ handle_dao_timer(void *ptr)
curr_instance.dag.state = DAG_REACHABLE; curr_instance.dag.state = DAG_REACHABLE;
} }
rpl_timers_dio_reset("Reachable"); rpl_timers_dio_reset("Reachable");
#endif /* !RPL_WITH_DAO_ACK */ /* There is no DAO-ACK, schedule a refresh. */
curr_instance.dag.dao_last_seqno = curr_instance.dag.dao_curr_seqno;
/* Send a DAO with own prefix as target and default lifetime */
rpl_icmp6_dao_output(curr_instance.default_lifetime);
#if !RPL_WITH_DAO_ACK
/* There is no DAO-ACK, schedule a refresh. Must be done after rpl_icmp6_dao_output,
because we increment curr_instance.dag.dao_curr_seqno for the next DAO (refresh).
Where there is DAO-ACK, the refresh is scheduled after reception of the ACK.
Happens when handle_dao_timer is called again next. */
schedule_dao_refresh(); schedule_dao_refresh();
#endif /* !RPL_WITH_DAO_ACK */ #endif /* !RPL_WITH_DAO_ACK */
/* Increment seqno */
RPL_LOLLIPOP_INCREMENT(curr_instance.dag.dao_last_seqno);
/* Send a DAO with own prefix as target and default lifetime */
rpl_icmp6_dao_output(curr_instance.default_lifetime);
} }
#if RPL_WITH_DAO_ACK #if RPL_WITH_DAO_ACK
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
@ -334,6 +309,32 @@ handle_dao_ack_timer(void *ptr)
rpl_icmp6_dao_ack_output(&curr_instance.dag.dao_ack_target, rpl_icmp6_dao_ack_output(&curr_instance.dag.dao_ack_target,
curr_instance.dag.dao_ack_sequence, RPL_DAO_ACK_UNCONDITIONAL_ACCEPT); curr_instance.dag.dao_ack_sequence, RPL_DAO_ACK_UNCONDITIONAL_ACCEPT);
} }
/*---------------------------------------------------------------------------*/
void
rpl_timers_notify_dao_ack(void)
{
/* The last DAO was ACKed. Schedule refresh to avoid route expiration. This
implicitly de-schedules resend_dao, as both share curr_instance.dag.dao_timer */
schedule_dao_refresh();
}
/*---------------------------------------------------------------------------*/
static void
resend_dao(void *ptr)
{
/* Increment transmission counter before sending */
curr_instance.dag.dao_transmissions++;
/* Send a DAO with own prefix as target and default lifetime */
rpl_icmp6_dao_output(curr_instance.default_lifetime);
/* Schedule next retransmission, or abort */
if(curr_instance.dag.dao_transmissions < RPL_DAO_MAX_RETRANSMISSIONS) {
schedule_dao_retransmission();
} else {
/* No more retransmissions. Perform local repair. */
rpl_local_repair("DAO max rtx");
return;
}
}
#endif /* RPL_WITH_DAO_ACK */ #endif /* RPL_WITH_DAO_ACK */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/*------------------------------- Probing----------------------------------- */ /*------------------------------- Probing----------------------------------- */

View File

@ -99,6 +99,11 @@ void rpl_timers_schedule_dao(void);
*/ */
void rpl_timers_schedule_dao_ack(uip_ipaddr_t *target, uint16_t sequence); void rpl_timers_schedule_dao_ack(uip_ipaddr_t *target, uint16_t sequence);
/**
* Let the rpl-timers module know that the last DAO was ACKed
*/
void rpl_timers_notify_dao_ack(void);
/** /**
* Schedule probing with delay RPL_PROBING_DELAY_FUNC() * Schedule probing with delay RPL_PROBING_DELAY_FUNC()
*/ */

View File

@ -198,7 +198,6 @@ struct rpl_dag {
uint8_t dio_counter; /* internal trickle timer state: redundancy counter */ uint8_t dio_counter; /* internal trickle timer state: redundancy counter */
uint8_t dao_last_seqno; /* the node's last sent DAO seqno */ uint8_t dao_last_seqno; /* the node's last sent DAO seqno */
uint8_t dao_last_acked_seqno; /* the last seqno we got an ACK for */ uint8_t dao_last_acked_seqno; /* the last seqno we got an ACK for */
uint8_t dao_curr_seqno; /* the node's current DAO seqno (sent or to be sent) */
uint8_t dao_transmissions; /* the number of transmissions for the current DAO */ uint8_t dao_transmissions; /* the number of transmissions for the current DAO */
enum rpl_dag_state state; enum rpl_dag_state state;