diff --git a/core/net/rpl/rpl-dag.c b/core/net/rpl/rpl-dag.c index e96f5e5d8..8443b176e 100644 --- a/core/net/rpl/rpl-dag.c +++ b/core/net/rpl/rpl-dag.c @@ -32,7 +32,7 @@ * * This file is part of the Contiki operating system. * - * $Id: rpl-dag.c,v 1.34 2010/10/25 20:03:37 nvt-se Exp $ + * $Id: rpl-dag.c,v 1.35 2010/10/27 00:46:40 nvt-se Exp $ */ /** * \file @@ -108,7 +108,7 @@ remove_parents(rpl_dag_t *dag, rpl_rank_t minimum_rank) for(p = list_head(dag->parents); p != NULL; p = p2) { p2 = p->next; - if(DAG_RANK(p->rank, dag) >= minimum_rank) { + if(p->rank >= minimum_rank) { rpl_remove_parent(dag, p); } } @@ -265,6 +265,7 @@ rpl_add_parent(rpl_dag_t *dag, rpl_dio_t *dio, uip_ipaddr_t *addr) p = memb_alloc(&parent_memb); if(p == NULL) { + RPL_STAT(rpl_stats.mem_overflows++); return NULL; } @@ -506,6 +507,7 @@ global_repair(uip_ipaddr_t *from, rpl_dag_t *dag, rpl_dio_t *dio) PRINTF("RPL: Participating in a global repair (version=%u, rank=%hu)\n", dag->version, dag->rank); + RPL_STAT(rpl_stats.global_repairs++); } /************************************************************************/ int @@ -521,6 +523,18 @@ rpl_repair_dag(rpl_dag_t *dag) } /************************************************************************/ void +rpl_local_repair(rpl_dag_t *dag) +{ + PRINTF("RPL: Starting a local DAG repair\n"); + + dag->rank = INFINITE_RANK; + remove_parents(dag, 0); + rpl_reset_dio_timer(dag, 1); + + RPL_STAT(rpl_stats.local_repairs++); +} +/************************************************************************/ +void rpl_recalculate_ranks(void) { rpl_dag_t *dag; @@ -560,9 +574,8 @@ rpl_process_parent_event(rpl_dag_t *dag, rpl_parent_t *p) if(rpl_select_parent(dag) == NULL) { /* No suitable parent; trigger a local repair. */ - PRINTF("RPL: No more parents, triggering a local repair\n"); - dag->rank = INFINITE_RANK; - rpl_reset_dio_timer(dag, 1); + PRINTF("RPL: No parents found in a DAG\n"); + rpl_local_repair(dag); return 1; } @@ -650,7 +663,7 @@ rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio) if(p == NULL) { if(RPL_PARENT_COUNT(dag) == RPL_MAX_PARENTS) { /* Try to make room for a new parent. */ - remove_parents(dag, DAG_RANK(dio->rank, dag)); + remove_parents(dag, dio->rank); } /* Add the DIO sender as a candidate parent. */ diff --git a/core/net/rpl/rpl-icmp6.c b/core/net/rpl/rpl-icmp6.c index 724287e23..19c335163 100644 --- a/core/net/rpl/rpl-icmp6.c +++ b/core/net/rpl/rpl-icmp6.c @@ -1,4 +1,3 @@ - /** * \addtogroup uip6 * @{ @@ -33,7 +32,7 @@ * * This file is part of the Contiki operating system. * - * $Id: rpl-icmp6.c,v 1.24 2010/10/25 19:49:12 nvt-se Exp $ + * $Id: rpl-icmp6.c,v 1.25 2010/10/27 00:46:40 nvt-se Exp $ */ /** * \file @@ -238,16 +237,24 @@ dio_input(void) len = 2 + buffer[i + 1]; } + if(len + i > buffer_length) { + PRINTF("RPL: Invalid DIO packet\n"); + RPL_STAT(rpl_stats.malformed_msgs++); + return; + } + switch(subopt_type) { case RPL_DIO_SUBOPT_DAG_MC: if(len < 7) { PRINTF("RPL: Invalid DAG MC, len = %d\n", len); + RPL_STAT(rpl_stats.malformed_msgs++); return; } break; case RPL_DIO_SUBOPT_ROUTE_INFO: if(len < 9) { PRINTF("RPL: Invalid destination prefix option, len = %d\n", len); + RPL_STAT(rpl_stats.malformed_msgs++); return; } /* flags is both preference and flags for now */ @@ -262,6 +269,8 @@ dio_input(void) (dio.destination_prefix.length + 7) / 8); } else { PRINTF("RPL: Invalid route infoprefix option, len = %d\n", len); + RPL_STAT(rpl_stats.malformed_msgs++); + return; } break; @@ -280,6 +289,7 @@ dio_input(void) case RPL_DIO_SUBOPT_PREFIX_INFO: if(len != 32) { PRINTF("RPL: DAG Prefix info not ok, len != 32\n"); + RPL_STAT(rpl_stats.malformed_msgs++); return; } dio.prefix_info.length = buffer[i + 2]; @@ -488,9 +498,9 @@ dao_input(void) /* Check if this is a DAO forwarding loop. */ p = rpl_find_parent(dag, &dao_sender_addr); if(p != NULL && p->rank < dag->rank) { - printf("RPL: Loop detected when receiving a unicast DAO from a node with a lower rank!\n"); - dag->rank = INFINITE_RANK; - rpl_reset_dio_timer(dag, 1); + printf("RPL: Loop detected when receiving a unicast DAO from a node with a lower rank! (%u < %u)\n", + DAG_RANK(p->rank, dag), DAG_RANK(dag->rank, dag)); + rpl_local_repair(dag); return; } } diff --git a/core/net/rpl/rpl.c b/core/net/rpl/rpl.c index dede06a29..519bf9b0f 100644 --- a/core/net/rpl/rpl.c +++ b/core/net/rpl/rpl.c @@ -32,7 +32,7 @@ * * This file is part of the Contiki operating system. * - * $Id: rpl.c,v 1.10 2010/10/22 13:50:13 nvt-se Exp $ + * $Id: rpl.c,v 1.11 2010/10/27 00:46:40 nvt-se Exp $ */ /** * \file @@ -51,6 +51,11 @@ #include "net/uip-debug.h" #include +#include + +#if RPL_CONF_STATS +rpl_stats_t rpl_stats; +#endif /************************************************************************/ extern uip_ds6_route_t uip_ds6_routing_table[UIP_DS6_ROUTE_NB]; @@ -204,5 +209,8 @@ rpl_init(void) rpl_reset_periodic_timer(); neighbor_info_subscribe(rpl_link_neighbor_callback); +#if RPL_CONF_STATS + memset(&rpl_stats, 0, sizeof(rpl_stats)); +#endif } /************************************************************************/ diff --git a/core/net/rpl/rpl.h b/core/net/rpl/rpl.h index 66f8a3b1d..da3350822 100644 --- a/core/net/rpl/rpl.h +++ b/core/net/rpl/rpl.h @@ -30,7 +30,7 @@ * * Author: Joakim Eriksson, Nicolas Tsiftes * - * $Id: rpl.h,v 1.21 2010/10/22 13:13:40 joxe Exp $ + * $Id: rpl.h,v 1.22 2010/10/27 00:46:40 nvt-se Exp $ */ #ifndef RPL_H @@ -241,6 +241,23 @@ struct rpl_dio { typedef struct rpl_dio rpl_dio_t; +#if RPL_CONF_STATS +/* Statistics for fault management. */ +struct rpl_stats { + uint16_t mem_overflows; + uint16_t local_repairs; + uint16_t global_repairs; + uint16_t malformed_msgs; +}; +typedef struct rpl_stats rpl_stats_t; + +extern rpl_stats_t rpl_stats; + +#define RPL_STAT(code) (code) +#else +#define RPL_STAT(code) +#endif /* RPL_CONF_STATS */ + /* Directed Acyclic Graph */ struct rpl_dag { /* DAG configuration */ @@ -297,6 +314,7 @@ void uip_rpl_input(void); rpl_dag_t *rpl_set_root(uip_ipaddr_t *); int rpl_set_prefix(rpl_dag_t *dag, uip_ipaddr_t *prefix, int len); int rpl_repair_dag(rpl_dag_t *dag); +void rpl_local_repair(rpl_dag_t *dag); int rpl_set_default_route(rpl_dag_t *dag, uip_ipaddr_t *from); void rpl_process_dio(uip_ipaddr_t *, rpl_dio_t *); int rpl_process_parent_event(rpl_dag_t *, rpl_parent_t *);