/** * 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; } } } }
/** * Grab the next topology entry. * * @param adr the address to look for * @return the entry found or NULL */ static struct tc_entry * tas_getnext_tc_entry(struct tc_entry *tc) { struct avl_node *node = avl_walk_next(&tc->vertex_node); return (node ? vertex_tree2tc(node) : NULL); }
/** * 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 */ }
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(); } }
int iterRouteTabNext(char *buff, int len) { struct avl_node *rt_tree_node; if (iterRouteTab == NULL) return -1; snprintf(buff, len, "destination~%s~gateway~%s~interface~%s~metric~%d~", rawIpAddrToString(&iterRouteTab->rt_dst.prefix, ipAddrLen), rawIpAddrToString(&iterRouteTab->rt_best->rtp_nexthop.gateway, ipAddrLen), if_ifwithindex_name(iterRouteTab->rt_best->rtp_nexthop.iif_index), iterRouteTab->rt_best->rtp_metric.hops); rt_tree_node = avl_walk_next(&iterRouteTab->rt_tree_node); if (rt_tree_node) { iterRouteTab = rt_tree2rt(rt_tree_node); } else { iterRouteTab = NULL; } return 0; }
/** * 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; } }
/* * olsr_spf_relax * * Explore all edges of a node and add the node * to the candidate tree if the if the aggregate * path cost is better. */ static void olsr_spf_relax(struct avl_tree *cand_tree, struct tc_entry *tc) { struct avl_node *edge_node; olsr_linkcost new_cost; #ifdef DEBUG #ifndef NODEBUG struct ipaddr_str buf, nbuf; struct lqtextbuffer lqbuffer; #endif /* NODEBUG */ OLSR_PRINTF(2, "SPF: exploring node %s, cost %s\n", olsr_ip_to_string(&buf, &tc->addr), get_linkcost_text(tc->path_cost, false, &lqbuffer)); #endif /* DEBUG */ /* * loop through all edges of this vertex. */ for (edge_node = avl_walk_first(&tc->edge_tree); edge_node; edge_node = avl_walk_next(edge_node)) { struct tc_entry *new_tc; struct tc_edge_entry *tc_edge = edge_tree2tc_edge(edge_node); /* * We are not interested in dead-end edges. */ if (!tc_edge->edge_inv) { #ifdef DEBUG OLSR_PRINTF(2, "SPF: ignoring edge %s\n", olsr_ip_to_string(&buf, &tc_edge->T_dest_addr)); if (!tc_edge->edge_inv) { OLSR_PRINTF(2, "SPF: no inverse edge\n"); } #endif /* DEBUG */ continue; } if (tc_edge->cost == LINK_COST_BROKEN) { #ifdef DEBUG OLSR_PRINTF(2, "SPF: ignore edge %s (broken)\n", olsr_ip_to_string(&buf, &tc_edge->T_dest_addr)); #endif /* DEBUG */ continue; } /* * total quality of the path through this vertex * to the destination of this edge */ new_cost = tc->path_cost + tc_edge->cost; #ifdef DEBUG OLSR_PRINTF(2, "SPF: exploring edge %s, cost %s\n", olsr_ip_to_string(&buf, &tc_edge->T_dest_addr), get_linkcost_text(new_cost, true, &lqbuffer)); #endif /* DEBUG */ /* * if it's better than the current path quality of this edge's * destination node, then we've found a better path to this node. */ new_tc = tc_edge->edge_inv->tc; if (new_cost < new_tc->path_cost) { /* if this node has been on the candidate tree delete it */ if (new_tc->path_cost < ROUTE_COST_BROKEN) { olsr_spf_del_cand_tree(cand_tree, new_tc); } /* re-insert on candidate tree with the better metric */ new_tc->path_cost = new_cost; olsr_spf_add_cand_tree(cand_tree, new_tc); /* pull-up the next-hop and bump the hop count */ if (tc->next_hop) { new_tc->next_hop = tc->next_hop; } new_tc->hops = tc->hops + 1; #ifdef DEBUG OLSR_PRINTF(2, "SPF: better path to %s, cost %s, via %s, hops %u\n", olsr_ip_to_string(&buf, &new_tc->addr), get_linkcost_text(new_cost, true, &lqbuffer), tc->next_hop ? olsr_ip_to_string(&nbuf, &tc->next_hop->neighbor_iface_addr) : "<none>", new_tc->hops); #endif /* DEBUG */ } } }