diff --git a/core/net/rpl/rpl-dag.c b/core/net/rpl/rpl-dag.c index dff633a72..d2593f97c 100644 --- a/core/net/rpl/rpl-dag.c +++ b/core/net/rpl/rpl-dag.c @@ -701,8 +701,8 @@ rpl_select_dag(rpl_instance_t *instance, rpl_parent_t *p) return best_dag; } /*---------------------------------------------------------------------------*/ -rpl_parent_t * -rpl_select_parent(rpl_dag_t *dag) +static rpl_parent_t * +best_parent(rpl_dag_t *dag) { rpl_parent_t *p, *best; @@ -720,6 +720,14 @@ rpl_select_parent(rpl_dag_t *dag) p = nbr_table_next(rpl_parents, p); } + return best; +} +/*---------------------------------------------------------------------------*/ +rpl_parent_t * +rpl_select_parent(rpl_dag_t *dag) +{ + rpl_parent_t *best = best_parent(dag); + if(best != NULL) { rpl_set_preferred_parent(dag, best); } @@ -1289,4 +1297,10 @@ rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio) p->dtsn = dio->dtsn; } /*---------------------------------------------------------------------------*/ +void +rpl_lock_parent(rpl_parent_t *p) +{ + nbr_table_lock(rpl_parents, p); +} +/*---------------------------------------------------------------------------*/ #endif /* UIP_CONF_IPV6 */ diff --git a/core/net/rpl/rpl-icmp6.c b/core/net/rpl/rpl-icmp6.c index 72aaa461b..7f22e7827 100644 --- a/core/net/rpl/rpl-icmp6.c +++ b/core/net/rpl/rpl-icmp6.c @@ -700,6 +700,33 @@ dao_input(void) } PRINTF("RPL: adding DAO route\n"); + + uip_ds6_nbr_t *nbr; + if((nbr = uip_ds6_nbr_lookup(&dao_sender_addr)) == NULL) { + if((nbr = uip_ds6_nbr_add(&dao_sender_addr, + (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER), + 0, NBR_REACHABLE)) != NULL) { + /* set reachable timer */ + stimer_set(&nbr->reachable, UIP_ND6_REACHABLE_TIME / 1000); + PRINTF("RPL: Neighbor added to neighbor cache "); + PRINT6ADDR(&dao_sender_addr); + PRINTF(", "); + PRINTLLADDR((uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER)); + PRINTF("\n"); + } else { + PRINTF("RPL: Out of Memory, dropping DAO from "); + PRINT6ADDR(&dao_sender_addr); + PRINTF(", "); + PRINTLLADDR((uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER)); + PRINTF("\n"); + return; + } + } else { + PRINTF("RPL: Neighbor already in neighbor cache\n"); + } + + rpl_lock_parent(p); + rep = rpl_add_route(dag, &prefix, prefixlen, &dao_sender_addr); if(rep == NULL) { RPL_STAT(rpl_stats.mem_overflows++); diff --git a/core/net/rpl/rpl-private.h b/core/net/rpl/rpl-private.h index a78e1dd8b..0aaee680e 100644 --- a/core/net/rpl/rpl-private.h +++ b/core/net/rpl/rpl-private.h @@ -304,6 +304,9 @@ uip_ds6_route_t *rpl_add_route(rpl_dag_t *dag, uip_ipaddr_t *prefix, int prefix_len, uip_ipaddr_t *next_hop); void rpl_purge_routes(void); +/* Lock a parent in the neighbor cache. */ +void rpl_lock_parent(rpl_parent_t *p); + /* Objective function. */ rpl_of_t *rpl_find_of(rpl_ocp_t);