/*---------------------------------------------------------------------------*/ static void handle_dao_timer(struct net_buf *not_used, void *ptr) { rpl_instance_t *instance; #if RPL_CONF_MULTICAST uip_mcast6_route_t *mcast_route; uint8_t i; #endif instance = (rpl_instance_t *)ptr; if(!dio_send_ok && uip_ds6_get_link_local(ADDR_PREFERRED) == NULL) { PRINTF("RPL: Postpone DAO transmission\n"); ctimer_set(NULL, &instance->dao_timer, CLOCK_SECOND, handle_dao_timer, instance); return; } /* Send the DAO to the DAO parent set -- the preferred parent in our case. */ if(instance->current_dag->preferred_parent != NULL) { PRINTF("RPL: handle_dao_timer - sending DAO\n"); /* Set the route lifetime to the default value. */ dao_output(instance->current_dag->preferred_parent, instance->default_lifetime); #if RPL_CONF_MULTICAST /* Send DAOs for multicast prefixes only if the instance is in MOP 3 */ if(instance->mop == RPL_MOP_STORING_MULTICAST) { /* Send a DAO for own multicast addresses */ for(i = 0; i < UIP_DS6_MADDR_NB; i++) { if(uip_ds6_if.maddr_list[i].isused && uip_is_addr_mcast_global(&uip_ds6_if.maddr_list[i].ipaddr)) { dao_output_target(instance->current_dag->preferred_parent, &uip_ds6_if.maddr_list[i].ipaddr, RPL_MCAST_LIFETIME); } } /* Iterate over multicast routes and send DAOs */ mcast_route = uip_mcast6_route_list_head(); while(mcast_route != NULL) { /* Don't send if it's also our own address, done that already */ if(uip_ds6_maddr_lookup(&mcast_route->group) == NULL) { dao_output_target(instance->current_dag->preferred_parent, &mcast_route->group, RPL_MCAST_LIFETIME); } mcast_route = list_item_next(mcast_route); } } #endif } else { PRINTF("RPL: No suitable DAO parent\n"); } ctimer_stop(&instance->dao_timer); if(etimer_expired(&instance->dao_lifetime_timer.etimer)) { set_dao_lifetime_timer(instance); } }
/*---------------------------------------------------------------------------*/ void rpl_purge_routes(void) { uip_ds6_route_t *r; uip_ipaddr_t prefix; rpl_dag_t *dag; rpl_instance_t *instance; //changed /* First pass, decrement lifetime */ r = uip_ds6_route_head(); while(r != NULL) { if(r->state.lifetime >= 1) { /* * If a route is at lifetime == 1, set it to 0, scheduling it for * immediate removal below. This achieves the same as the original code, * which would delete lifetime <= 1 */ r->state.lifetime--; } r = uip_ds6_route_next(r); } /* Second pass, remove dead routes */ r = uip_ds6_route_head(); while(r != NULL) { /*Pre-change handle second_instance*/ if(r->state.lifetime < 1) { /* Routes with lifetime == 1 have only just been decremented from 2 to 1, * thus we want to keep them. Hence < and not <= */ uip_ipaddr_copy(&prefix, &r->ipaddr); uip_ds6_route_rm(r); r = uip_ds6_route_head(); PRINTF("No more routes to "); PRINT6ADDR(&prefix); /*Changed*/ instance = rpl_get_instance(r->state.instance_id); dag = instance->current_dag; //dag1 = second_instance->current_dag; /* Propagate this information with a No-Path DAO to preferred parent if we are not a RPL Root */ if(dag->rank != ROOT_RANK(instance)) { PRINTF(" -> generate No-Path DAO\n"); dao_output_target(dag->preferred_parent, &prefix, RPL_ZERO_LIFETIME); /* Don't schedule more than 1 No-Path DAO, let next iteration handle that */ return; } PRINTF("\n"); } else { r = uip_ds6_route_next(r); } } }
static void handle_host_timer(void *ptr) { rpl_parent_t *parent; rpl_instance_t *instance; uip_ds6_nbr_t *nbr; uip_ds6_route_t *route; instance = (rpl_instance_t *)ptr; parent = instance->current_dag->preferred_parent; nbr = nbr_table_head(ds6_neighbors); while(nbr != NULL) { if(nbr->isrouter == ISROUTER_TESTING) { nbr->isrouter = ISROUTER_NO; route = uip_ds6_route_lookup_by_nexthop(&nbr->ipaddr); if(route != NULL) { dao_output_target(parent, &route->ipaddr, instance->default_lifetime); } } nbr = nbr_table_next(ds6_neighbors, nbr); } }
/*---------------------------------------------------------------------------*/ int rpl_update_header_empty(void) { rpl_instance_t *instance; int uip_ext_opt_offset; int last_uip_ext_len; rpl_parent_t *parent; last_uip_ext_len = uip_ext_len; uip_ext_len = 0; uip_ext_opt_offset = 2; PRINTF("RPL: Verifying the presence of the RPL header option\n"); switch(UIP_IP_BUF->proto) { case UIP_PROTO_HBHO: if(UIP_HBHO_BUF->len != RPL_HOP_BY_HOP_LEN - 8) { PRINTF("RPL: Hop-by-hop extension header has wrong size\n"); uip_ext_len = last_uip_ext_len; return 0; } if(UIP_EXT_HDR_OPT_RPL_BUF->opt_type != UIP_EXT_HDR_OPT_RPL) { PRINTF("RPL: Non RPL Hop-by-hop option support not implemented\n"); uip_ext_len = last_uip_ext_len; return 0; } if(UIP_EXT_HDR_OPT_RPL_BUF->opt_len != RPL_HDR_OPT_LEN) { PRINTF("RPL: RPL Hop-by-hop option has wrong length\n"); uip_ext_len = last_uip_ext_len; return 0; } instance = rpl_get_instance(UIP_EXT_HDR_OPT_RPL_BUF->instance); if(instance == NULL || !instance->used || !instance->current_dag->joined) { PRINTF("RPL: Unable to add hop-by-hop extension header: incorrect instance\n"); return 0; } break; default: #if RPL_INSERT_HBH_OPTION PRINTF("RPL: No hop-by-hop option found, creating it\n"); if(uip_len + RPL_HOP_BY_HOP_LEN > UIP_BUFSIZE - UIP_LLH_LEN) { PRINTF("RPL: Packet too long: impossible to add hop-by-hop option\n"); uip_ext_len = last_uip_ext_len; return 0; } set_rpl_opt(uip_ext_opt_offset); uip_ext_len = last_uip_ext_len + RPL_HOP_BY_HOP_LEN; #endif return 0; } switch(UIP_EXT_HDR_OPT_BUF->type) { case UIP_EXT_HDR_OPT_RPL: PRINTF("RPL: Updating RPL option\n"); UIP_EXT_HDR_OPT_RPL_BUF->senderrank = UIP_HTONS(instance->current_dag->rank); /* Check the direction of the down flag, as per Section 11.2.2.3, which states that if a packet is going down it should in general not go back up again. If this happens, a RPL_HDR_OPT_FWD_ERR should be flagged. */ if((UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_DOWN)) { if(uip_ds6_route_lookup(&UIP_IP_BUF->destipaddr) == NULL) { UIP_EXT_HDR_OPT_RPL_BUF->flags |= RPL_HDR_OPT_FWD_ERR; PRINTF("RPL forwarding error\n"); /* We should send back the packet to the originating parent, but it is not feasible yet, so we send a No-Path DAO instead */ PRINTF("RPL generate No-Path DAO\n"); parent = rpl_get_parent((uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER)); if(parent != NULL) { dao_output_target(parent, &UIP_IP_BUF->destipaddr, RPL_ZERO_LIFETIME); } /* Drop packet */ return 1; } } else { /* Set the down extension flag correctly as described in Section 11.2 of RFC6550. If the packet progresses along a DAO route, the down flag should be set. */ if(uip_ds6_route_lookup(&UIP_IP_BUF->destipaddr) == NULL) { /* No route was found, so this packet will go towards the RPL root. If so, we should not set the down flag. */ UIP_EXT_HDR_OPT_RPL_BUF->flags &= ~RPL_HDR_OPT_DOWN; PRINTF("RPL option going up\n"); } else { /* A DAO route was found so we set the down flag. */ UIP_EXT_HDR_OPT_RPL_BUF->flags |= RPL_HDR_OPT_DOWN; PRINTF("RPL option going down\n"); } } uip_ext_len = last_uip_ext_len; return 0; default: PRINTF("RPL: Multi Hop-by-hop options not implemented\n"); uip_ext_len = last_uip_ext_len; return 0; } }