/** * Delete a prefix from the prefix tree hanging off a lsdb (tc) entry. */ void olsr_delete_routing_table(union olsr_ip_addr *dst, int plen, union olsr_ip_addr *originator) { #ifdef DEBUG struct ipaddr_str dstbuf, origbuf; #endif struct tc_entry *tc; struct rt_path *rtp; struct avl_node *node; struct olsr_ip_prefix prefix; /* * No bogus prefix lengths. */ if (plen > olsr_cnf->maxplen) { return; } tc = olsr_lookup_tc_entry(originator); if (!tc) { return; } /* * Grab the rt_path for the prefix. */ prefix.prefix = *dst; prefix.prefix_len = plen; node = avl_find(&tc->prefix_tree, &prefix); if (node) { rtp = rtp_prefix_tree2rtp(node); olsr_delete_rt_path(rtp); #ifdef DEBUG OLSR_PRINTF(1, "RIB: del prefix %s/%u from %s\n", olsr_ip_to_string(&dstbuf, dst), plen, olsr_ip_to_string(&origbuf, originator)); #endif /* overload the hna change bit for flagging a prefix change */ changes_hna = OLSR_TRUE; } }
/** * Look through the gateway list and select the best gateway * depending on the distance to this router */ static void gw_default_choose_gateway(void) { uint64_t cost_ipv4_threshold = UINT64_MAX; uint64_t cost_ipv6_threshold = UINT64_MAX; bool eval_cost_ipv4_threshold = false; bool eval_cost_ipv6_threshold = false; struct gateway_entry *inet_ipv4 = NULL; struct gateway_entry *inet_ipv6 = NULL; uint64_t cost_ipv4 = UINT64_MAX; uint64_t cost_ipv6 = UINT64_MAX; struct gateway_entry *gw; struct tc_entry *tc; bool dual; if (olsr_cnf->smart_gw_thresh) { /* determine the path cost thresholds */ gw = olsr_get_ipv4_inet_gateway(); if (gw) { tc = olsr_lookup_tc_entry(&gw->originator); if (tc) { uint64_t cost = gw_default_weigh_costs(tc->path_cost, gw->uplink, gw->downlink); cost_ipv4_threshold = gw_default_calc_threshold(cost); eval_cost_ipv4_threshold = true; } } gw = olsr_get_ipv6_inet_gateway(); if (gw) { tc = olsr_lookup_tc_entry(&gw->originator); if (tc) { uint64_t cost = gw_default_weigh_costs(tc->path_cost, gw->uplink, gw->downlink); cost_ipv6_threshold = gw_default_calc_threshold(cost); eval_cost_ipv6_threshold = true; } } } OLSR_FOR_ALL_GATEWAY_ENTRIES(gw) { uint64_t path_cost; tc = olsr_lookup_tc_entry(&gw->originator); if (!tc) { /* gateways should not exist without tc entry */ continue; } if (tc->path_cost == ROUTE_COST_BROKEN) { /* do not consider nodes with an infinite ETX */ continue; } if (!gw->uplink || !gw->downlink) { /* do not consider nodes without bandwidth or with a uni-directional link */ continue; } /* determine the path cost */ path_cost = gw_default_weigh_costs(tc->path_cost, gw->uplink, gw->downlink); if (!gw_def_finished_ipv4 && gw->ipv4 && gw->ipv4nat == olsr_cnf->smart_gw_allow_nat && path_cost < cost_ipv4 && (!eval_cost_ipv4_threshold || (path_cost < cost_ipv4_threshold))) { inet_ipv4 = gw; cost_ipv4 = path_cost; } if (!gw_def_finished_ipv6 && gw->ipv6 && path_cost < cost_ipv6 && (!eval_cost_ipv6_threshold || (path_cost < cost_ipv6_threshold))) { inet_ipv6 = gw; cost_ipv6 = path_cost; } } OLSR_FOR_ALL_GATEWAY_ENTRIES_END(gw) /* determine if we found an IPv4 and IPv6 gateway */ gw_def_finished_ipv4 |= (inet_ipv4 != NULL); gw_def_finished_ipv6 |= (inet_ipv6 != NULL); /* determine if we are dealing with a dual stack gateway */ dual = (inet_ipv4 == inet_ipv6) && (inet_ipv4 != NULL); if (inet_ipv4) { /* we are dealing with an IPv4 or dual stack gateway */ olsr_set_inet_gateway(&inet_ipv4->originator, true, dual); } if (inet_ipv6 && !dual) { /* we are dealing with an IPv6-only gateway */ olsr_set_inet_gateway(&inet_ipv6->originator, false, true); } if ((olsr_cnf->smart_gw_thresh == 0) && gw_def_finished_ipv4 && gw_def_finished_ipv6) { /* stop looking for a better gateway */ olsr_stop_timer(gw_def_timer); gw_def_timer = NULL; } }
/** * Determine the best gateway for uplink: this is the cluster leader. * * Loop over all gateways to find the best one and return it. * When no best gateway is found then we return ourselves so that the behaviour * degrades gracefully. * * A gateway is better when the sum of its uplink and downlink are greater than * the previous best gateway. In case of a tie, the lowest IP address wins. * * @param bestGateway * a pointer to the variable in which to store the best gateway */ void getBestUplinkGateway(union olsr_ip_addr * bestGateway) { struct gateway_entry *gw_best = NULL; unsigned long long gw_best_value = 0; struct gateway_entry *gw; OLSR_FOR_ALL_GATEWAY_ENTRIES(gw) { bool eval4 = false; bool eval6 = false; struct tc_entry * tc = olsr_lookup_tc_entry(&gw->originator); if (!tc || (tc->path_cost == ROUTE_COST_BROKEN) || (!gw->uplink || !gw->downlink)) { /* gateways should not exist without tc entry */ /* do not consider nodes with an infinite ETX */ /* do not consider nodes without bandwidth or with a uni-directional link */ continue; } if (gw == olsr_get_inet_gateway(false)) { eval4 = true; } else if (gw->ipv4 && (olsr_cnf->ip_version == AF_INET || olsr_cnf->use_niit) && (olsr_cnf->smart_gw_allow_nat || !gw->ipv4nat)) { eval4 = true; } if (gw == olsr_get_inet_gateway(true)) { eval6 = true; } else if (gw->ipv6 && olsr_cnf->ip_version == AF_INET6) { eval6 = true; } if (eval4 || eval6) { unsigned long long gw_value = gw_speed(gw); if (!gw_best || (gw_value > gw_best_value)) { gw_best = gw; gw_best_value = gw_value; } else if (gw_value == gw_best_value) { bool gwHaslowerIpAddress = false; if (eval4) { gwHaslowerIpAddress = (ip4cmp(&gw->originator.v4, &gw_best->originator.v4) < 0); } else /* eval6 */{ gwHaslowerIpAddress = (ip6cmp(&gw->originator.v6, &gw_best->originator.v6) < 0); } if (gwHaslowerIpAddress) { gw_best = gw; gw_best_value = gw_value; } } } } OLSR_FOR_ALL_GATEWAY_ENTRIES_END(gw) if (!gw_best) { /* degrade gracefully */ *bestGateway = olsr_cnf->main_addr; return; } *bestGateway = gw_best->originator; }