/*---------------------------------------------------------------------------*/ uip_ipaddr_t * rpl_get_parent_ipaddr(rpl_parent_t *p) { rimeaddr_t *lladdr = nbr_table_get_lladdr(rpl_parents, p); return uip_ds6_nbr_ipaddr_from_lladdr((uip_lladdr_t *)lladdr); }
/*---------------------------------------------------------------------------*/ void rpl_print_neighbor_list() { if(default_instance != NULL && default_instance->current_dag != NULL && default_instance->of != NULL && default_instance->of->calculate_rank != NULL) { 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); clock_time_t now = clock_time(); printf("RPL: rank %u dioint %u, %u nbr(s)\n", curr_rank, curr_dio_interval, uip_ds6_nbr_num()); while(p != NULL) { uip_ds6_nbr_t *nbr = rpl_get_nbr(p); printf("RPL: nbr %3u %5u, %5u => %5u %c%c (last tx %u min ago)\n", nbr_table_get_lladdr(rpl_parents, p)->u8[7], p->rank, nbr ? nbr->link_metric : 0, default_instance->of->calculate_rank(p, 0), default_instance->current_dag == p->dag ? 'd' : ' ', p == default_instance->current_dag->preferred_parent ? '*' : ' ', (unsigned)((now - p->last_tx_time) / (60 * CLOCK_SECOND))); p = nbr_table_next(rpl_parents, p); } printf("RPL: end of list\n"); } }
/*---------------------------------------------------------------------------*/ static uip_lladdr_t * uip_ds6_route_nexthop_lladdr(uip_ds6_route_t *route) { if(route != NULL) { return (uip_lladdr_t *)nbr_table_get_lladdr(nbr_routes, route->routes); } else { return NULL; } }
/*---------------------------------------------------------------------------*/ uip_ds6_nbr_t * rpl_get_nbr(rpl_parent_t *parent) { linkaddr_t *lladdr = NULL; lladdr = nbr_table_get_lladdr(rpl_parents, parent); if(lladdr != NULL) { return nbr_table_get_from_lladdr(ds6_neighbors, lladdr); } else { return NULL; } }
/*---------------------------------------------------------------------------*/ uip_ds6_nbr_t * rpl_get_nbr(rpl_parent_t *parent) { linkaddr_t *lladdr = NULL; lladdr = nbr_table_get_lladdr(rpl_parents, parent); if(lladdr != NULL) { return uip_ds6_nbr_ll_lookup((uip_lladdr_t*) lladdr); } else { return NULL; } }
/*---------------------------------------------------------------------------*/ static void handle_probing_timer(void *ptr) { rpl_instance_t *instance = (rpl_instance_t *)ptr; rpl_parent_t *probing_target = RPL_PROBING_SELECT_FUNC(instance->current_dag); /* Perform probing */ if(probing_target != NULL && rpl_get_parent_ipaddr(probing_target) != NULL) { PRINTF("RPL: probing %3u\n", nbr_table_get_lladdr(rpl_parents, probing_target)->u8[7]); /* Send probe, e.g. unicast DIO or DIS */ RPL_PROBING_SEND_FUNC(instance, rpl_get_parent_ipaddr(probing_target)); } /* Schedule next probing */ rpl_schedule_probing(instance); #if DEBUG rpl_print_neighbor_list(); #endif }
/*---------------------------------------------------------------------------*/ static void eb_input(struct input_packet *current_input) { /* PRINTF("TSCH: EB received\n"); */ frame802154_t frame; /* Verify incoming EB (does its ASN match our Rx time?), * and update our join priority. */ struct ieee802154_ies eb_ies; if(tsch_packet_parse_eb(current_input->payload, current_input->len, &frame, &eb_ies, NULL, 1)) { /* PAN ID check and authentication done at rx time */ #if TSCH_AUTOSELECT_TIME_SOURCE if(!tsch_is_coordinator) { /* Maintain EB received counter for every neighbor */ struct eb_stat *stat = (struct eb_stat *)nbr_table_get_from_lladdr(eb_stats, &frame.src_addr); if(stat == NULL) { stat = (struct eb_stat *)nbr_table_add_lladdr(eb_stats, &frame.src_addr); } if(stat != NULL) { stat->rx_count++; stat->jp = eb_ies.join_priority; best_neighbor_eb_count = MAX(best_neighbor_eb_count, stat->rx_count); } /* Select best time source */ struct eb_stat *best_stat = NULL; stat = nbr_table_head(eb_stats); while(stat != NULL) { /* Is neighbor eligible as a time source? */ if(stat->rx_count > best_neighbor_eb_count / 2) { if(best_stat == NULL || stat->jp < best_stat->jp) { best_stat = stat; } } stat = nbr_table_next(eb_stats, stat); } /* Update time source */ if(best_stat != NULL) { tsch_queue_update_time_source(nbr_table_get_lladdr(eb_stats, best_stat)); tsch_join_priority = best_stat->jp + 1; } } #endif struct tsch_neighbor *n = tsch_queue_get_time_source(); /* Did the EB come from our time source? */ if(n != NULL && linkaddr_cmp((linkaddr_t *)&frame.src_addr, &n->addr)) { /* Check for ASN drift */ int32_t asn_diff = ASN_DIFF(current_input->rx_asn, eb_ies.ie_asn); if(asn_diff != 0) { /* We disagree with our time source's ASN -- leave the network */ PRINTF("TSCH:! ASN drifted by %ld, leaving the network\n", asn_diff); tsch_disassociate(); } if(eb_ies.ie_join_priority >= TSCH_MAX_JOIN_PRIORITY) { /* Join priority unacceptable. Leave network. */ PRINTF("TSCH:! EB JP too high %u, leaving the network\n", eb_ies.ie_join_priority); tsch_disassociate(); } else { #if TSCH_AUTOSELECT_TIME_SOURCE /* Update join priority */ if(tsch_join_priority != eb_ies.ie_join_priority + 1) { PRINTF("TSCH: update JP from EB %u -> %u\n", tsch_join_priority, eb_ies.ie_join_priority + 1); tsch_join_priority = eb_ies.ie_join_priority + 1; } #endif /* TSCH_AUTOSELECT_TIME_SOURCE */ } } } }
/*---------------------------------------------------------------------------*/ const uip_lladdr_t * uip_ds6_nbr_get_ll(const uip_ds6_nbr_t *nbr) { return (const uip_lladdr_t *)nbr_table_get_lladdr(ds6_neighbors, nbr); }
/*---------------------------------------------------------------------------*/ void uip_ds6_route_rm(uip_ds6_route_t *route) { struct uip_ds6_route_neighbor_route *neighbor_route; #if DEBUG != DEBUG_NONE assert_nbr_routes_list_sane(); #endif /* DEBUG != DEBUG_NONE */ if(route != NULL && route->neighbor_routes != NULL) { PRINTF("uip_ds6_route_rm: removing route: "); PRINT6ADDR(&route->ipaddr); PRINTF("\n"); /* Remove the route from the route list */ list_remove(routelist, route); /* Find the corresponding neighbor_route and remove it. */ for(neighbor_route = list_head(route->neighbor_routes->route_list); neighbor_route != NULL && neighbor_route->route != route; neighbor_route = list_item_next(neighbor_route)); if(neighbor_route == NULL) { PRINTF("uip_ds6_route_rm: neighbor_route was NULL for "); uip_debug_ipaddr_print(&route->ipaddr); PRINTF("\n"); } list_remove(route->neighbor_routes->route_list, neighbor_route); if(list_head(route->neighbor_routes->route_list) == NULL) { /* If this was the only route using this neighbor, remove the neighbor from the table - this implicitly unlocks nexthop */ #if (DEBUG) & DEBUG_ANNOTATE uip_ipaddr_t *nexthop = uip_ds6_route_nexthop(route); if(nexthop != NULL) { ANNOTATE("#L %u 0\n", nexthop->u8[sizeof(uip_ipaddr_t) - 1]); } #endif /* (DEBUG) & DEBUG_ANNOTATE */ PRINTF("uip_ds6_route_rm: removing neighbor too\n"); nbr_table_remove(nbr_routes, route->neighbor_routes->route_list); #ifdef NETSTACK_CONF_ROUTING_NEIGHBOR_REMOVED_CALLBACK NETSTACK_CONF_ROUTING_NEIGHBOR_REMOVED_CALLBACK( (const linkaddr_t *)nbr_table_get_lladdr(nbr_routes, route->neighbor_routes->route_list)); #endif } memb_free(&routememb, route); memb_free(&neighborroutememb, neighbor_route); num_routes--; PRINTF("uip_ds6_route_rm num %d\n", num_routes); #if UIP_DS6_NOTIFICATIONS call_route_callback(UIP_DS6_NOTIFICATION_ROUTE_RM, &route->ipaddr, uip_ds6_route_nexthop(route)); #endif #ifdef NETSTACK_CONF_ROUTE_REMOVED_CALLBACK NETSTACK_CONF_ROUTE_REMOVED_CALLBACK(&route->ipaddr); #endif /* NETSTACK_CONF_ROUTE_REMOVED_CALLBACK*/ } #if DEBUG != DEBUG_NONE assert_nbr_routes_list_sane(); #endif /* DEBUG != DEBUG_NONE */ return; }