/*---------------------------------------------------------------------------*/ int rpl_process_parent_event(rpl_instance_t *instance, rpl_parent_t *p) { int return_value; #if DEBUG rpl_rank_t old_rank; old_rank = instance->current_dag->rank; #endif /* DEBUG */ return_value = 1; if(!acceptable_rank(p->dag, p->rank)) { /* The candidate parent is no longer valid: the rank increase resulting from the choice of it as a parent would be too high. */ PRINTF("RPL: Unacceptable rank %u\n", (unsigned)p->rank); rpl_nullify_parent(p); if(p != instance->current_dag->preferred_parent) { return 0; } else { return_value = 0; } } if(rpl_select_dag(instance, p) == NULL) { /* No suitable parent; trigger a local repair. */ PRINTF("RPL: No parents found in any DAG\n"); rpl_local_repair(instance); return 0; } #if DEBUG if(DAG_RANK(old_rank, instance) != DAG_RANK(instance->current_dag->rank, instance)) { PRINTF("RPL: Moving in the instance from rank %hu to %hu\n", DAG_RANK(old_rank, instance), DAG_RANK(instance->current_dag->rank, instance)); if(instance->current_dag->rank != INFINITE_RANK) { PRINTF("RPL: The preferred parent is "); PRINT6ADDR(rpl_get_parent_ipaddr (instance->current_dag->preferred_parent)); PRINTF(" (rank %u)\n", (unsigned)DAG_RANK(instance->current_dag->preferred_parent->rank, instance)); } else { PRINTF("RPL: We don't have any parent"); } } #endif /* DEBUG */ return return_value; }
/*---------------------------------------------------------------------------*/ int rpl_verify_header(int uip_ext_opt_offset) { rpl_instance_t *instance; int down; uint16_t sender_rank; uint8_t sender_closer; uip_ds6_route_t *route; rpl_parent_t *sender = NULL; if(UIP_HBHO_BUF->len != RPL_HOP_BY_HOP_LEN - 8) { PRINTF("RPL: Hop-by-hop extension header has wrong size\n"); return 1; } if(UIP_EXT_HDR_OPT_RPL_BUF->opt_type != UIP_EXT_HDR_OPT_RPL) { PRINTF("RPL: Non RPL Hop-by-hop option\n"); return 1; } if(UIP_EXT_HDR_OPT_RPL_BUF->opt_len != RPL_HDR_OPT_LEN) { PRINTF("RPL: Bad header option! (wrong length)\n"); return 1; } instance = rpl_get_instance(UIP_EXT_HDR_OPT_RPL_BUF->instance); if(instance == NULL) { PRINTF("RPL: Unknown instance: %u\n", UIP_EXT_HDR_OPT_RPL_BUF->instance); return 1; } if(UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_FWD_ERR) { PRINTF("RPL: Forward error!\n"); /* We should try to repair it by removing the neighbor that caused the packet to be forwareded in the first place. We drop any routes that go through the neighbor that sent the packet to us. */ route = uip_ds6_route_lookup(&UIP_IP_BUF->destipaddr); if(route != NULL) { uip_ds6_route_rm(route); } RPL_STAT(rpl_stats.forward_errors++); /* Trigger DAO retransmission */ rpl_reset_dio_timer(instance); /* drop the packet as it is not routable */ return 1; } if(!instance->current_dag->joined) { PRINTF("RPL: No DAG in the instance\n"); return 1; } down = 0; if(UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_DOWN) { down = 1; } sender_rank = UIP_HTONS(UIP_EXT_HDR_OPT_RPL_BUF->senderrank); sender_closer = sender_rank < instance->current_dag->rank; PRINTF("RPL: Packet going %s, sender closer %d (%d < %d)\n", down == 1 ? "down" : "up", sender_closer, sender_rank, instance->current_dag->rank ); sender = nbr_table_get_from_lladdr(rpl_parents, packetbuf_addr(PACKETBUF_ADDR_SENDER)); if(sender != NULL && (UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_RANK_ERR)) { /* A rank error was signalled, attempt to repair it by updating * the sender's rank from ext header */ sender->rank = sender_rank; rpl_select_dag(instance, sender); } if((down && !sender_closer) || (!down && sender_closer)) { PRINTF("RPL: Loop detected - senderrank: %d my-rank: %d sender_closer: %d\n", sender_rank, instance->current_dag->rank, sender_closer); /* Attempt to repair the loop by sending a unicast DIO back to the sender * so that it gets a fresh update of our rank. */ if(sender != NULL) { instance->unicast_dio_target = sender; rpl_schedule_unicast_dio_immediately(instance); } if(UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_RANK_ERR) { RPL_STAT(rpl_stats.loop_errors++); PRINTF("RPL: Rank error signalled in RPL option!\n"); /* Packet must be dropped and dio trickle timer reset, see RFC6550 - 11.2.2.2 */ rpl_reset_dio_timer(instance); return 1; } PRINTF("RPL: Single error tolerated\n"); RPL_STAT(rpl_stats.loop_warnings++); UIP_EXT_HDR_OPT_RPL_BUF->flags |= RPL_HDR_OPT_RANK_ERR; return 0; } PRINTF("RPL: Rank OK\n"); return 0; }