/** * Print the routingtree to STDOUT * */ void olsr_print_routing_table(struct avl_tree *tree) { #ifndef NODEBUG /* The whole function makes no sense without it. */ struct avl_node *rt_tree_node; struct lqtextbuffer lqbuffer; OLSR_PRINTF(6, "ROUTING TABLE\n"); for (rt_tree_node = avl_walk_first(tree); rt_tree_node != NULL; rt_tree_node = avl_walk_next(rt_tree_node)) { struct avl_node *rtp_tree_node; struct ipaddr_str prefixstr, origstr, gwstr; struct rt_entry *rt = rt_tree2rt(rt_tree_node); /* first the route entry */ OLSR_PRINTF(6, "%s/%u, via %s, best-originator %s\n", olsr_ip_to_string(&prefixstr, &rt->rt_dst.prefix), rt->rt_dst.prefix_len, olsr_ip_to_string(&origstr, &rt->rt_nexthop.gateway), olsr_ip_to_string(&gwstr, &rt->rt_best->rtp_originator)); /* walk the per-originator path tree of routes */ for (rtp_tree_node = avl_walk_first(&rt->rt_path_tree); rtp_tree_node != NULL; rtp_tree_node = avl_walk_next(rtp_tree_node)) { struct rt_path *rtp = rtp_tree2rtp(rtp_tree_node); OLSR_PRINTF(6, "\tfrom %s, cost %s, metric %u, via %s, %s, v %u\n", olsr_ip_to_string(&origstr, &rtp->rtp_originator), get_linkcost_text(rtp->rtp_metric.cost, true, &lqbuffer), rtp->rtp_metric.hops, olsr_ip_to_string(&gwstr, &rtp-> rtp_nexthop. gateway), if_ifwithindex_name(rt->rt_nexthop.iif_index), rtp->rtp_version); } } #endif /* NODEBUG */ tree = NULL; /* squelch compiler warnings */ }
/** * Check the version number of all route paths hanging off a route entry. * If a route does not match the current routing tree number, remove it * from the global originator tree for that rt_entry. * Reset the best route pointer. */ static void olsr_delete_outdated_routes(struct rt_entry *rt) { struct rt_path *rtp; struct avl_node *rtp_tree_node, *next_rtp_tree_node; for (rtp_tree_node = avl_walk_first(&rt->rt_path_tree); rtp_tree_node != NULL; rtp_tree_node = next_rtp_tree_node) { /* * pre-fetch the next node before loosing context. */ next_rtp_tree_node = avl_walk_next(rtp_tree_node); rtp = rtp_tree2rtp(rtp_tree_node); /* * check the version number which gets incremented on every SPF run. * comparing for unequalness avoids handling version number wraps. */ if (routingtree_version != rtp->rtp_version) { /* remove from the originator tree */ avl_delete(&rt->rt_path_tree, rtp_tree_node); rtp->rtp_rt = NULL; if (rt->rt_best == rtp) { rt->rt_best = NULL; } } } }
/** * run best route selection among a * set of identical prefixes. */ void olsr_rt_best(struct rt_entry *rt) { /* grab the first entry */ struct avl_node *node = avl_walk_first(&rt->rt_path_tree); assert(node != 0); /* should not happen */ rt->rt_best = rtp_tree2rtp(node); /* walk all remaining originator entries */ while ((node = avl_walk_next(node))) { struct rt_path *rtp = rtp_tree2rtp(node); if (olsr_cmp_rtp(rtp, rt->rt_best, current_inetgw)) { rt->rt_best = rtp; } } if (0 == rt->rt_dst.prefix_len) { current_inetgw = rt->rt_best; } }
void olsr_delete_interface_routes(int if_index) { struct rt_entry *rt; bool triggerUpdate = false; OLSR_FOR_ALL_RT_ENTRIES(rt) { bool mightTrigger = false; struct rt_path *rtp; struct avl_node *rtp_tree_node, *next_rtp_tree_node; /* run through all routing paths of route */ for (rtp_tree_node = avl_walk_first(&rt->rt_path_tree); rtp_tree_node != NULL; rtp_tree_node = next_rtp_tree_node) { /* * pre-fetch the next node before loosing context. */ next_rtp_tree_node = avl_walk_next(rtp_tree_node); rtp = rtp_tree2rtp(rtp_tree_node); /* nexthop use lost interface ? */ if (rtp->rtp_nexthop.iif_index == if_index) { /* remove from the originator tree */ avl_delete(&rt->rt_path_tree, rtp_tree_node); rtp->rtp_rt = NULL; if (rt->rt_best == rtp) { rt->rt_best = NULL; mightTrigger = true; } } } if (mightTrigger) { if (!rt->rt_path_tree.count) { /* oops, all routes are gone - flush the route head */ avl_delete(&routingtree, rt_tree_node); /* do not dequeue route because they are already gone */ } triggerUpdate = true; } } OLSR_FOR_ALL_RT_ENTRIES_END(rt) /* trigger route update if necessary */ if (triggerUpdate) { olsr_update_rib_routes(); olsr_update_kernel_routes(); } }