RPL probing: now using link-stats to first prioritize probing of non-fresh parents, and to support urgent probing (fast probing of a potential new preferred parent
This commit is contained in:
parent
426e10c3ed
commit
c5cf8608e9
@ -291,7 +291,7 @@
|
||||
#ifdef RPL_CONF_PROBING_SELECT_FUNC
|
||||
#define RPL_PROBING_SELECT_FUNC RPL_CONF_PROBING_SELECT_FUNC
|
||||
#else
|
||||
#define RPL_PROBING_SELECT_FUNC(dag) get_probing_target((dag))
|
||||
#define RPL_PROBING_SELECT_FUNC get_probing_target
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -314,8 +314,7 @@
|
||||
#ifdef RPL_CONF_PROBING_DELAY_FUNC
|
||||
#define RPL_PROBING_DELAY_FUNC RPL_CONF_PROBING_DELAY_FUNC
|
||||
#else
|
||||
#define RPL_PROBING_DELAY_FUNC() ((RPL_PROBING_INTERVAL / 2) \
|
||||
+ random_rand() % (RPL_PROBING_INTERVAL))
|
||||
#define RPL_PROBING_DELAY_FUNC get_probing_delay
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -96,12 +96,13 @@ rpl_print_neighbor_list(void)
|
||||
int curr_dio_interval = default_instance->dio_intcurrent;
|
||||
int curr_rank = default_instance->current_dag->rank;
|
||||
rpl_parent_t *p = nbr_table_head(rpl_parents);
|
||||
const struct link_stats *stats = rpl_get_parent_link_stats(p);
|
||||
clock_time_t clock_now = clock_time();
|
||||
|
||||
printf("RPL: OCP %u rank %u dioint %u, nbr count %u\n",
|
||||
default_instance->of->ocp, curr_rank, curr_dio_interval, uip_ds6_nbr_num());
|
||||
while(p != NULL) {
|
||||
printf("RPL: nbr %3u %5u, %5u => %5u -- %5u %c%c (last tx %u min ago)\n",
|
||||
const struct link_stats *stats = rpl_get_parent_link_stats(p);
|
||||
printf("RPL: nbr %3u %5u, %5u => %5u -- %2u %c%c (last tx %u min ago)\n",
|
||||
rpl_get_parent_ipaddr(p)->u8[15],
|
||||
p->rank,
|
||||
rpl_get_parent_link_metric(p),
|
||||
@ -109,7 +110,7 @@ rpl_print_neighbor_list(void)
|
||||
stats != NULL ? stats->freshness : 0,
|
||||
link_stats_is_fresh(stats) ? 'f' : ' ',
|
||||
p == default_instance->current_dag->preferred_parent ? 'p' : ' ',
|
||||
(unsigned)((now - p->last_tx_time) / (60 * CLOCK_SECOND))
|
||||
(unsigned)((clock_now - stats->last_tx_time) / (60 * CLOCK_SECOND))
|
||||
);
|
||||
p = nbr_table_next(rpl_parents, p);
|
||||
}
|
||||
@ -868,6 +869,10 @@ rpl_select_parent(rpl_dag_t *dag)
|
||||
if(rpl_parent_is_fresh(best)) {
|
||||
rpl_set_preferred_parent(dag, best);
|
||||
dag->rank = rpl_rank_via_parent(dag->preferred_parent);
|
||||
} else {
|
||||
/* Probe the new best parent shortly in order to get a fresh estimate */
|
||||
dag->instance->urgent_probing_target = best;
|
||||
rpl_schedule_probing(dag->instance);
|
||||
}
|
||||
} else {
|
||||
rpl_set_preferred_parent(dag, best);
|
||||
|
@ -56,6 +56,14 @@
|
||||
void RPL_CALLBACK_NEW_DIO_INTERVAL(uint8_t dio_interval);
|
||||
#endif /* RPL_CALLBACK_NEW_DIO_INTERVAL */
|
||||
|
||||
#ifdef RPL_PROBING_SELECT_FUNC
|
||||
rpl_parent_t *RPL_PROBING_SELECT_FUNC(rpl_dag_t *dag);
|
||||
#endif /* RPL_PROBING_SELECT_FUNC */
|
||||
|
||||
#ifdef RPL_PROBING_DELAY_FUNC
|
||||
clock_time_t RPL_PROBING_DELAY_FUNC(rpl_dag_t *dag);
|
||||
#endif /* RPL_PROBING_DELAY_FUNC */
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static struct ctimer periodic_timer;
|
||||
|
||||
@ -359,42 +367,57 @@ rpl_schedule_unicast_dio_immediately(rpl_instance_t *instance)
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#if RPL_WITH_PROBING
|
||||
static rpl_parent_t *
|
||||
clock_time_t
|
||||
get_probing_delay(rpl_dag_t *dag)
|
||||
{
|
||||
if(dag != NULL && dag->instance != NULL
|
||||
&& dag->instance->urgent_probing_target != NULL) {
|
||||
/* Urgent probing needed (to find out if a neighbor may become preferred parent) */
|
||||
return random_rand() % (CLOCK_SECOND * 10);
|
||||
} else {
|
||||
/* Else, use normal probing interval */
|
||||
return ((RPL_PROBING_INTERVAL) / 2) + random_rand() % (RPL_PROBING_INTERVAL);
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
rpl_parent_t *
|
||||
get_probing_target(rpl_dag_t *dag)
|
||||
{
|
||||
/* Returns the next probing target. The current implementation probes the current
|
||||
* preferred parent if we have not updated its link for RPL_PROBING_EXPIRATION_TIME.
|
||||
/* Returns the next probing target. The current implementation probes the urgent
|
||||
* probing target if any, or the preferred parent if its link statistics need refresh.
|
||||
* Otherwise, it picks at random between:
|
||||
* (1) selecting the best parent not updated for RPL_PROBING_EXPIRATION_TIME
|
||||
* (1) selecting the best parent with non-fresh link statistics
|
||||
* (2) selecting the least recently updated parent
|
||||
*/
|
||||
|
||||
rpl_parent_t *p;
|
||||
rpl_parent_t *probing_target = NULL;
|
||||
rpl_rank_t probing_target_rank = INFINITE_RANK;
|
||||
/* min_last_tx is the clock time RPL_PROBING_EXPIRATION_TIME in the past */
|
||||
clock_time_t min_last_tx = clock_time();
|
||||
min_last_tx = min_last_tx > 2 * RPL_PROBING_EXPIRATION_TIME
|
||||
? min_last_tx - RPL_PROBING_EXPIRATION_TIME : 1;
|
||||
clock_time_t probing_target_age = 0;
|
||||
clock_time_t clock_now = clock_time();
|
||||
|
||||
if(dag == NULL ||
|
||||
dag->instance == NULL ||
|
||||
dag->preferred_parent == NULL) {
|
||||
dag->instance == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Our preferred parent needs probing */
|
||||
if(dag->preferred_parent->last_tx_time < min_last_tx) {
|
||||
probing_target = dag->preferred_parent;
|
||||
/* There is an urgent probing target */
|
||||
if(dag->instance->urgent_probing_target != NULL) {
|
||||
return dag->instance->urgent_probing_target;
|
||||
}
|
||||
|
||||
/* With 50% probability: probe best parent not updated for RPL_PROBING_EXPIRATION_TIME */
|
||||
if(probing_target == NULL && (random_rand() % 2) == 0) {
|
||||
/* The preferred parent needs probing */
|
||||
if(dag->preferred_parent != NULL && !rpl_parent_is_fresh(dag->preferred_parent)) {
|
||||
return dag->preferred_parent;
|
||||
}
|
||||
|
||||
/* With 50% probability: probe best non-fresh parent */
|
||||
if(random_rand() % 2 == 0) {
|
||||
p = nbr_table_head(rpl_parents);
|
||||
while(p != NULL) {
|
||||
if(p->dag == dag && p->last_tx_time < min_last_tx) {
|
||||
if(p->dag == dag && !rpl_parent_is_fresh(p)) {
|
||||
/* p is in our dag and needs probing */
|
||||
rpl_rank_t p_rank = dag->instance->of->calculate_rank(p, 0);
|
||||
rpl_rank_t p_rank = rpl_rank_via_parent(p);
|
||||
if(probing_target == NULL
|
||||
|| p_rank < probing_target_rank) {
|
||||
probing_target = p;
|
||||
@ -405,14 +428,16 @@ get_probing_target(rpl_dag_t *dag)
|
||||
}
|
||||
}
|
||||
|
||||
/* The default probing target is the least recently updated parent */
|
||||
/* If we still do not have a probing target: pick the least recently updated parent */
|
||||
if(probing_target == NULL) {
|
||||
p = nbr_table_head(rpl_parents);
|
||||
while(p != NULL) {
|
||||
if(p->dag == dag) {
|
||||
const struct link_stats *stats =rpl_get_parent_link_stats(p);
|
||||
if(p->dag == dag && stats != NULL) {
|
||||
if(probing_target == NULL
|
||||
|| p->last_tx_time < probing_target->last_tx_time) {
|
||||
|| clock_now - stats->last_tx_time > probing_target_age) {
|
||||
probing_target = p;
|
||||
probing_target_age = clock_now - stats->last_tx_time;
|
||||
}
|
||||
}
|
||||
p = nbr_table_next(rpl_parents, p);
|
||||
@ -431,11 +456,14 @@ handle_probing_timer(void *ptr)
|
||||
|
||||
/* Perform probing */
|
||||
if(target_ipaddr != NULL) {
|
||||
PRINTF("RPL: probing %u ((last tx %u min ago))\n",
|
||||
nbr_table_get_lladdr(rpl_parents, probing_target)->u8[7],
|
||||
(unsigned)((clock_time() - probing_target->last_tx_time) / (60 * CLOCK_SECOND)));
|
||||
/* Send probe (unicast DIO or DIS) */
|
||||
PRINTF("RPL: probing %u %s last tx %u min ago\n",
|
||||
rpl_get_parent_llpaddr(probing_target)->u8[7],
|
||||
instance->urgent_probing_target != NULL ? "(urgent)" : "",
|
||||
(unsigned)((clock_time() - probing_target->last_tx_time) / (60 * CLOCK_SECOND)),
|
||||
);
|
||||
/* Send probe, e.g. unicast DIO or DIS */
|
||||
RPL_PROBING_SEND_FUNC(instance, target_ipaddr);
|
||||
instance->urgent_probing_target = NULL;
|
||||
}
|
||||
|
||||
/* Schedule next probing */
|
||||
@ -449,7 +477,7 @@ handle_probing_timer(void *ptr)
|
||||
void
|
||||
rpl_schedule_probing(rpl_instance_t *instance)
|
||||
{
|
||||
ctimer_set(&instance->probing_timer, RPL_PROBING_DELAY_FUNC(),
|
||||
ctimer_set(&instance->probing_timer, RPL_PROBING_DELAY_FUNC(instance->current_dag),
|
||||
handle_probing_timer, instance);
|
||||
}
|
||||
#endif /* RPL_WITH_PROBING */
|
||||
|
@ -246,6 +246,7 @@ struct rpl_instance {
|
||||
clock_time_t dio_next_delay; /* delay for completion of dio interval */
|
||||
#if RPL_WITH_PROBING
|
||||
struct ctimer probing_timer;
|
||||
rpl_parent_t *urgent_probing_target;
|
||||
#endif /* RPL_WITH_PROBING */
|
||||
struct ctimer dio_timer;
|
||||
struct ctimer dao_timer;
|
||||
|
Loading…
Reference in New Issue
Block a user