/** * 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; } }
/** * 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 cost_ipv4_threshold_valid = false; bool cost_ipv6_threshold_valid = false; struct gateway_entry *chosen_gw_ipv4 = NULL; struct gateway_entry *chosen_gw_ipv6 = NULL; uint64_t chosen_gw_ipv4_costs = UINT64_MAX; uint64_t chosen_gw_ipv6_costs = UINT64_MAX; struct gateway_entry *gw; bool dual = false; if (olsr_cnf->smart_gw_thresh) { /* determine the path cost thresholds */ uint64_t cost = gw_default_getcosts(olsr_get_inet_gateway(false)); if (cost != UINT64_MAX) { cost_ipv4_threshold = gw_default_calc_threshold(cost); cost_ipv4_threshold_valid = true; } cost = gw_default_getcosts(olsr_get_inet_gateway(true)); if (cost != UINT64_MAX) { cost_ipv6_threshold = gw_default_calc_threshold(cost); cost_ipv6_threshold_valid = true; } } OLSR_FOR_ALL_GATEWAY_ENTRIES(gw) { uint64_t gw_cost = gw_default_getcosts(gw); if (gw_cost == UINT64_MAX) { /* never select a node with infinite costs */ continue; } if (gw_def_choose_new_ipv4_gw) { bool gw_eligible_v4 = gw->ipv4 /* && (olsr_cnf->ip_version == AF_INET || olsr_cnf->use_niit) *//* contained in gw_def_choose_new_ipv4_gw */ && (olsr_cnf->smart_gw_allow_nat || !gw->ipv4nat); if (gw_eligible_v4 && gw_cost < chosen_gw_ipv4_costs && (!cost_ipv4_threshold_valid || (gw_cost < cost_ipv4_threshold))) { chosen_gw_ipv4 = gw; chosen_gw_ipv4_costs = gw_cost; } } if (gw_def_choose_new_ipv6_gw) { bool gw_eligible_v6 = gw->ipv6 /* && olsr_cnf->ip_version == AF_INET6 *//* contained in gw_def_choose_new_ipv6_gw */; if (gw_eligible_v6 && gw_cost < chosen_gw_ipv6_costs && (!cost_ipv6_threshold_valid || (gw_cost < cost_ipv6_threshold))) { chosen_gw_ipv6 = gw; chosen_gw_ipv6_costs = gw_cost; } } } OLSR_FOR_ALL_GATEWAY_ENTRIES_END(gw) /* determine if we should keep looking for IPv4 and/or IPv6 gateways */ gw_def_choose_new_ipv4_gw = gw_def_choose_new_ipv4_gw && (chosen_gw_ipv4 == NULL); gw_def_choose_new_ipv6_gw = gw_def_choose_new_ipv6_gw && (chosen_gw_ipv6 == NULL); /* determine if we are dealing with a dual stack gateway */ dual = chosen_gw_ipv4 && (chosen_gw_ipv4 == chosen_gw_ipv6); if (chosen_gw_ipv4) { /* we are dealing with an IPv4 or dual stack gateway */ olsr_set_inet_gateway(&chosen_gw_ipv4->originator, chosen_gw_ipv4_costs, true, dual); } if (chosen_gw_ipv6 && !dual) { /* we are dealing with an IPv6-only gateway */ olsr_set_inet_gateway(&chosen_gw_ipv6->originator, chosen_gw_ipv6_costs, false, true); } if ((olsr_cnf->smart_gw_thresh == 0) && !gw_def_choose_new_ipv4_gw && !gw_def_choose_new_ipv6_gw) { /* stop looking for a better gateway */ olsr_stop_timer(gw_def_timer); gw_def_timer = NULL; } }