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();
101 index += snprintf(buf+index, buflen-index,
102 "%5u, %5u => %5u -- %2u %c%c%c%c%c",
106 stats != NULL ? stats->freshness : 0,
108 nbr == best ?
'b' :
' ',
110 link_stats_is_fresh(stats) ?
'f' :
' ',
111 nbr == curr_instance.dag.preferred_parent ?
'p' :
' ' 113 if(index >= buflen) {
116 if(stats->last_tx_time > 0) {
117 index += snprintf(buf+index, buflen-index,
118 " (last tx %u min ago",
119 (
unsigned)((clock_now - stats->last_tx_time) / (60 *
CLOCK_SECOND)));
121 index += snprintf(buf+index, buflen-index,
124 if(index >= buflen) {
127 if(nbr->better_parent_since > 0) {
128 index += snprintf(buf+index, buflen-index,
129 ", better since %u min)",
130 (
unsigned)((clock_now - nbr->better_parent_since) / (60 *
CLOCK_SECOND)));
132 index += snprintf(buf+index, buflen-index,
141 if(curr_instance.used) {
142 int curr_dio_interval = curr_instance.dag.dio_intcurrent;
143 int curr_rank = curr_instance.dag.rank;
146 LOG_INFO(
"nbr: own state, addr ");
148 LOG_INFO_(
", DAG state: %s, MOP %u OCP %u rank %u max-rank %u, dioint %u, nbr count %u (%s)\n",
150 curr_instance.mop, curr_instance.of->ocp, curr_rank,
151 max_acceptable_rank(),
156 LOG_INFO(
"nbr: %s\n", buf);
157 nbr = nbr_table_next(rpl_neighbors, nbr);
159 LOG_INFO(
"nbr: end of list\n");
168 for(nbr = nbr_table_head(rpl_neighbors);
170 nbr = nbr_table_next(rpl_neighbors, nbr)) {
182 return nbr_table_get_from_lladdr(ds6_neighbors, lladdr);
195 if(nbr == curr_instance.dag.urgent_probing_target) {
196 curr_instance.dag.urgent_probing_target = NULL;
198 if(nbr == curr_instance.dag.unicast_dio_target) {
199 curr_instance.dag.unicast_dio_target = NULL;
201 nbr_table_remove(rpl_neighbors, nbr);
208 return nbr_table_get_from_lladdr(rpl_neighbors, (linkaddr_t *)addr);
214 if(nbr != NULL && curr_instance.of->nbr_is_acceptable_parent != NULL) {
215 return curr_instance.of->nbr_is_acceptable_parent(nbr);
223 if(nbr != NULL && curr_instance.of->nbr_link_metric != NULL) {
224 return curr_instance.of->nbr_link_metric(nbr);
232 if(nbr != NULL && curr_instance.of->rank_via_nbr != NULL) {
233 return curr_instance.of->rank_via_nbr(nbr);
235 return RPL_INFINITE_RANK;
241 return nbr_table_get_lladdr(rpl_neighbors, nbr);
248 return uip_ds6_nbr_ipaddr_from_lladdr((uip_lladdr_t *)lladdr);
251 const struct link_stats *
255 return link_stats_from_lladdr(lladdr);
262 return link_stats_is_fresh(stats);
273 if(ds6_nbr == NULL || ds6_nbr->state != NBR_REACHABLE) {
285 return nbr != NULL && nbr->rank < curr_instance.dag.rank;
291 if(curr_instance.dag.preferred_parent != nbr) {
292 LOG_INFO(
"parent switch: ");
298 #ifdef RPL_CALLBACK_PARENT_SWITCH 299 RPL_CALLBACK_PARENT_SWITCH(curr_instance.dag.preferred_parent, nbr);
304 nbr_table_unlock(rpl_neighbors, curr_instance.dag.preferred_parent);
305 nbr_table_lock(rpl_neighbors, nbr);
308 uip_ds6_defrt_rm(uip_ds6_defrt_lookup(
312 curr_instance.dag.preferred_parent =
nbr;
322 LOG_INFO(
"removing all neighbors\n");
324 nbr = nbr_table_head(rpl_neighbors);
326 remove_neighbor(nbr);
327 nbr = nbr_table_next(rpl_neighbors, nbr);
339 const uip_lladdr_t *lladdr = uip_ds6_nbr_get_ll(ds6_nbr);
340 return nbr_table_get_from_lladdr(rpl_neighbors, (linkaddr_t *)lladdr);
344 best_parent(
int fresh_only)
349 if(curr_instance.used == 0) {
354 for(nbr = nbr_table_head(rpl_neighbors); nbr != NULL; nbr = nbr_table_next(rpl_neighbors, nbr)) {
356 if(!acceptable_rank(nbr->rank) || !curr_instance.of->nbr_is_acceptable_parent(nbr)) {
370 if(ds6_nbr == NULL || ds6_nbr->state != NBR_REACHABLE) {
377 best = curr_instance.of->best_parent(best, nbr);
393 best = best_parent(0);
399 curr_instance.dag.urgent_probing_target = NULL;
407 if(curr_instance.dag.urgent_probing_target == NULL) {
408 LOG_INFO(
"best parent is not fresh, schedule urgent probing to ");
411 curr_instance.dag.urgent_probing_target = best;
418 if(best == curr_instance.dag.preferred_parent) {
423 best_fresh = best_parent(1);
424 if(best_fresh == NULL) {
425 if(curr_instance.dag.preferred_parent == NULL) {
450 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.
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.
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.
An entry in the nbr cache.
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.