46 #include "net/routing/rpl-lite/rpl.h" 47 #include "net/link-stats.h" 48 #include "net/nbr-table.h" 53 #define LOG_MODULE "RPL" 54 #define LOG_LEVEL LOG_LEVEL_RPL 57 #ifdef RPL_CALLBACK_PARENT_SWITCH 61 static rpl_nbr_t * best_parent(
int fresh_only);
65 NBR_TABLE_GLOBAL(
rpl_nbr_t, rpl_neighbors);
69 max_acceptable_rank(
void)
71 if(curr_instance.max_rankinc == 0) {
73 return RPL_INFINITE_RANK;
76 return MIN((uint32_t)curr_instance.dag.lowest_rank + curr_instance.max_rankinc, RPL_INFINITE_RANK);
82 acceptable_rank(rpl_rank_t rank)
84 return rank != RPL_INFINITE_RANK
86 && rank <= max_acceptable_rank();
97 if(LOG_WITH_COMPACT_ADDR) {
102 if(index >= buflen) {
105 index += snprintf(buf+index, buflen-index,
106 "%5u, %5u => %5u -- %2u %c%c%c%c%c",
110 stats != NULL ? stats->freshness : 0,
112 nbr == best ?
'b' :
' ',
114 link_stats_is_fresh(stats) ?
'f' :
' ',
115 nbr == curr_instance.dag.preferred_parent ?
'p' :
' ' 117 if(index >= buflen) {
120 if(stats != NULL && stats->last_tx_time > 0) {
121 index += snprintf(buf+index, buflen-index,
122 " (last tx %u min ago",
123 (
unsigned)((clock_now - stats->last_tx_time) / (60 *
CLOCK_SECOND)));
125 index += snprintf(buf+index, buflen-index,
128 if(index >= buflen) {
131 if(nbr->better_parent_since > 0) {
132 index += snprintf(buf+index, buflen-index,
133 ", better since %u min)",
134 (
unsigned)((clock_now - nbr->better_parent_since) / (60 *
CLOCK_SECOND)));
136 index += snprintf(buf+index, buflen-index,
145 if(curr_instance.used) {
146 int curr_dio_interval = curr_instance.dag.dio_intcurrent;
147 int curr_rank = curr_instance.dag.rank;
150 LOG_INFO(
"nbr: own state, addr ");
152 LOG_INFO_(
", DAG state: %s, MOP %u OCP %u rank %u max-rank %u, dioint %u, nbr count %u (%s)\n",
154 curr_instance.mop, curr_instance.of->ocp, curr_rank,
155 max_acceptable_rank(),
160 LOG_INFO(
"nbr: %s\n", buf);
161 nbr = nbr_table_next(rpl_neighbors, nbr);
163 LOG_INFO(
"nbr: end of list\n");
172 for(nbr = nbr_table_head(rpl_neighbors);
174 nbr = nbr_table_next(rpl_neighbors, nbr)) {
200 if(nbr == curr_instance.dag.urgent_probing_target) {
201 curr_instance.dag.urgent_probing_target = NULL;
205 if(nbr == curr_instance.dag.unicast_dio_target) {
206 curr_instance.dag.unicast_dio_target = NULL;
208 nbr_table_remove(rpl_neighbors, nbr);
215 return nbr_table_get_from_lladdr(rpl_neighbors, (linkaddr_t *)addr);
221 if(nbr != NULL && curr_instance.of->nbr_is_acceptable_parent != NULL) {
222 return curr_instance.of->nbr_is_acceptable_parent(nbr);
230 if(nbr != NULL && curr_instance.of->nbr_link_metric != NULL) {
231 return curr_instance.of->nbr_link_metric(nbr);
239 if(nbr != NULL && curr_instance.of->rank_via_nbr != NULL) {
240 return curr_instance.of->rank_via_nbr(nbr);
242 return RPL_INFINITE_RANK;
248 return nbr_table_get_lladdr(rpl_neighbors, nbr);
258 const struct link_stats *
262 return link_stats_from_lladdr(lladdr);
269 return link_stats_is_fresh(stats);
280 if(ds6_nbr == NULL || ds6_nbr->state != NBR_REACHABLE) {
292 return nbr != NULL && nbr->rank < curr_instance.dag.rank;
298 if(curr_instance.dag.preferred_parent != nbr) {
299 LOG_INFO(
"parent switch: ");
305 #ifdef RPL_CALLBACK_PARENT_SWITCH 306 RPL_CALLBACK_PARENT_SWITCH(curr_instance.dag.preferred_parent, nbr);
311 nbr_table_unlock(rpl_neighbors, curr_instance.dag.preferred_parent);
312 nbr_table_lock(rpl_neighbors, nbr);
315 uip_ds6_defrt_rm(uip_ds6_defrt_lookup(
319 curr_instance.dag.preferred_parent =
nbr;
320 curr_instance.dag.unprocessed_parent_switch =
true;
330 LOG_INFO(
"removing all neighbors\n");
337 nbr = nbr_table_head(rpl_neighbors);
339 remove_neighbor(nbr);
340 nbr = nbr_table_next(rpl_neighbors, nbr);
353 return nbr_table_get_from_lladdr(rpl_neighbors, (linkaddr_t *)lladdr);
357 best_parent(
int fresh_only)
362 if(curr_instance.used == 0) {
367 for(nbr = nbr_table_head(rpl_neighbors); nbr != NULL; nbr = nbr_table_next(rpl_neighbors, nbr)) {
370 || !curr_instance.of->nbr_is_acceptable_parent(nbr)) {
384 if(ds6_nbr == NULL || ds6_nbr->state != NBR_REACHABLE) {
391 best = curr_instance.of->best_parent(best, nbr);
407 best = best_parent(0);
413 curr_instance.dag.urgent_probing_target = NULL;
421 if(curr_instance.dag.urgent_probing_target == NULL) {
422 LOG_INFO(
"best parent is not fresh, schedule urgent probing to ");
425 curr_instance.dag.urgent_probing_target = best;
432 if(best == curr_instance.dag.preferred_parent) {
437 best_fresh = best_parent(1);
438 if(best_fresh == NULL) {
439 if(curr_instance.dag.preferred_parent == NULL) {
464 nbr_table_register(rpl_neighbors, (nbr_table_callback *)remove_neighbor);
const linkaddr_t * rpl_neighbor_get_lladdr(rpl_nbr_t *nbr)
Returns a neighbors's link-layer address.
uip_ipaddr_t * rpl_neighbor_get_ipaddr(rpl_nbr_t *nbr)
Returns a neighbor's (link-local) IPv6 address.
static uip_ds6_nbr_t * nbr
Pointer to llao option in uip_buf.
#define ROOT_RANK
Rank of a root node.
static uip_ds6_addr_t * addr
Pointer to a nbr cache entry.
void rpl_neighbor_remove_all(void)
Empty the RPL neighbor table.
void rpl_schedule_probing_now(void)
Schedule probing within a few seconds.
rpl_nbr_t * rpl_neighbor_get_from_ipaddr(uip_ipaddr_t *addr)
Returns a neighbor from its link-local IPv6 address.
int rpl_neighbor_is_fresh(rpl_nbr_t *nbr)
Tells wether we have fresh link information towards a given neighbor.
uint16_t rpl_neighbor_get_link_metric(rpl_nbr_t *nbr)
Returns a neighbor's link metric.
int rpl_neighbor_is_parent(rpl_nbr_t *nbr)
Tells whether a neighbor is in the parent set.
int rpl_dag_root_is_root(void)
Tells whether we are DAG root or not.
int rpl_neighbor_count(void)
Returns the number of nodes in the RPL neighbor table.
const char * rpl_dag_state_to_str(enum rpl_dag_state state)
Returns a textual description of the current DAG state.
void rpl_timers_schedule_state_update(void)
Schedule a state update ASAP.
void rpl_neighbor_init(void)
Initialize rpl-dag-neighbor module.
#define CLOCK_SECOND
A second, measured in system clock time.
Header file for the IP address manipulation library.
uip_ipaddr_t * uip_ds6_nbr_ipaddr_from_lladdr(const uip_lladdr_t *lladdr)
Get an IPv6 address associated with a specified link-layer address.
uip_ds6_nbr_t * uip_ds6_nbr_lookup(const uip_ipaddr_t *ipaddr)
Get the neighbor cache associated with a specified IPv6 address.
const struct link_stats * rpl_neighbor_get_link_stats(rpl_nbr_t *nbr)
Returns a neighbor's link statistics.
All information related to a RPL neighbor.
clock_time_t clock_time(void)
Get the current clock time.
void rpl_neighbor_print_list(const char *str)
Prints a summary of all RPL neighbors and their properties.
const uip_ipaddr_t * rpl_get_global_address(void)
Get one of the node's global addresses.
void rpl_dag_update_state(void)
Updates RPL internal state: selects preferred parent, updates rank & metreic container, triggers control traffic accordingly and updates uIP6 internal state.
int rpl_neighbor_is_acceptable_parent(rpl_nbr_t *nbr)
Tells whether a nbr is acceptable as per the OF's definition.
int log_6addr_compact_snprint(char *buf, size_t size, const uip_ipaddr_t *ipaddr)
Write at most size - 1 characters of the IP address to the output string, in a compact representation...
uip_ds6_nbr_t * uip_ds6_nbr_ll_lookup(const uip_lladdr_t *lladdr)
Get the neighbor cache associated with a specified link-layer address.
const uip_lladdr_t * uip_ds6_nbr_get_ll(const uip_ds6_nbr_t *nbr)
Get the link-layer address associated with a specified nbr cache.
rpl_rank_t rpl_neighbor_rank_via_nbr(rpl_nbr_t *nbr)
Returns our rank if selecting a given parent as preferred parent.
void rpl_neighbor_set_preferred_parent(rpl_nbr_t *nbr)
Set current RPL preferred parent and update DS6 default route accordingly.
Header file for the logging system
rpl_nbr_t * rpl_neighbor_select_best(void)
Returns the best candidate for preferred parent.
int rpl_neighbor_snprint(char *buf, int buflen, rpl_nbr_t *nbr)
Print a textual description of RPL neighbor into a string.
rpl_nbr_t * rpl_neighbor_get_from_lladdr(uip_lladdr_t *addr)
Returns a neighbor from its link-layer address.
The default nbr_table entry (when UIP_DS6_NBR_MULTI_IPV6_ADDRS is disabled), that implements nbr cach...
int rpl_neighbor_is_reachable(rpl_nbr_t *nbr)
Tells wether we a given neighbor is reachable.
int uiplib_ipaddr_snprint(char *buf, size_t size, const uip_ipaddr_t *addr)
Write at most size - 1 characters of the IP address to the output string.