Repository navigation
UCT: prioritize routes with longer subnet masks in the reachability check #11033
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -28,9 +28,7 @@ | |
| typedef struct { | ||
| const struct sockaddr *sa_remote; | ||
| int if_index; | ||
| int found; | ||
| int allow_default_gw; /* Allow matching default | ||
| gateway routes */ | ||
| int netmask_len; | ||
| } ucs_netlink_route_info_t; | ||
|
|
||
|
|
||
|
|
@@ -249,44 +247,29 @@ ucs_netlink_parse_rt_entry_cb(const struct nlmsghdr *nlh, void *arg) | |
| return UCS_INPROGRESS; | ||
| } | ||
|
|
||
| static void ucs_netlink_lookup_route(ucs_netlink_route_info_t *info) | ||
| static int | ||
| ucs_netlink_lookup_in_iface_rules(const struct sockaddr *sa_remote, | ||
| ucs_netlink_rt_rules_t *iface_rules) | ||
| { | ||
| ucs_netlink_rt_rules_t *iface_rules; | ||
| int found_netmask_len = -1; | ||
| ucs_netlink_route_entry_t *curr_entry; | ||
| khiter_t iter; | ||
|
|
||
| iter = kh_get(ucs_netlink_rt_cache, &ucs_netlink_routing_table_cache, | ||
| info->if_index); | ||
| if (iter == kh_end(&ucs_netlink_routing_table_cache)) { | ||
| info->found = 0; | ||
| return; | ||
| } | ||
|
|
||
| iface_rules = &kh_val(&ucs_netlink_routing_table_cache, iter); | ||
| ucs_array_for_each(curr_entry, iface_rules) { | ||
|
|
||
| if ((curr_entry->subnet_prefix_len == 0) && !info->allow_default_gw) { | ||
| ucs_trace("iface_index=%d: skipping default gateway route", | ||
| info->if_index); | ||
| continue; | ||
| } | ||
|
|
||
| if (ucs_sockaddr_is_same_subnet( | ||
| info->sa_remote, | ||
| (const struct sockaddr *)&curr_entry->dest, | ||
| curr_entry->subnet_prefix_len)) { | ||
| info->found = 1; | ||
| return; | ||
| if ((curr_entry->subnet_prefix_len > found_netmask_len) && | ||
| ucs_sockaddr_is_same_subnet( | ||
| sa_remote, (const struct sockaddr*)&curr_entry->dest, | ||
| curr_entry->subnet_prefix_len)) { | ||
| found_netmask_len = curr_entry->subnet_prefix_len; | ||
| } | ||
| } | ||
|
|
||
| return found_netmask_len; | ||
| } | ||
|
|
||
| int ucs_netlink_route_exists(int if_index, const struct sockaddr *sa_remote, | ||
| int allow_default_gw) | ||
| static void ucs_netlink_init_routing_table_cache(void) | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I could actually leave it as before and only trigger the cache initialization from
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe init the cache in ucs_netlink_lookup_route? |
||
| { | ||
| static ucs_init_once_t init_once = UCS_INIT_ONCE_INITIALIZER; | ||
| struct rtmsg rtm = {0}; | ||
| ucs_netlink_route_info_t info; | ||
|
|
||
| UCS_INIT_ONCE(&init_once) { | ||
| rtm.rtm_table = RT_TABLE_UNSPEC; /* fetch all the tables */ | ||
|
|
@@ -300,13 +283,67 @@ int ucs_netlink_route_exists(int if_index, const struct sockaddr *sa_remote, | |
| sizeof(rtm), ucs_netlink_parse_rt_entry_cb, | ||
| NULL); | ||
| } | ||
| } | ||
|
|
||
| info.if_index = if_index; | ||
| info.sa_remote = sa_remote; | ||
| info.found = 0; | ||
| info.allow_default_gw = allow_default_gw; | ||
| static void ucs_netlink_lookup_route(ucs_netlink_route_info_t *info) | ||
| { | ||
| ucs_netlink_rt_rules_t *iface_rules; | ||
| khiter_t iter; | ||
|
|
||
| ucs_netlink_init_routing_table_cache(); | ||
|
|
||
| iter = kh_get(ucs_netlink_rt_cache, &ucs_netlink_routing_table_cache, | ||
| info->if_index); | ||
| if (iter == kh_end(&ucs_netlink_routing_table_cache)) { | ||
| return; | ||
| } | ||
|
|
||
| iface_rules = &kh_val(&ucs_netlink_routing_table_cache, iter); | ||
| info->netmask_len = ucs_netlink_lookup_in_iface_rules(info->sa_remote, | ||
| iface_rules); | ||
| } | ||
|
|
||
| static int ucs_netlink_max_netmask_len(const struct sockaddr *sa_remote) | ||
| { | ||
| int max_netmask_len = -1; | ||
| ucs_netlink_rt_rules_t iface_rules; | ||
|
|
||
| kh_foreach_value(&ucs_netlink_routing_table_cache, iface_rules, { | ||
| int curr_netmask_len = ucs_netlink_lookup_in_iface_rules(sa_remote, | ||
| &iface_rules); | ||
| if (curr_netmask_len > max_netmask_len) { | ||
| max_netmask_len = curr_netmask_len; | ||
| } | ||
| }) | ||
|
|
||
| return max_netmask_len; | ||
| } | ||
|
|
||
| int ucs_netlink_route_exists(int if_index, const struct sockaddr *sa_remote, | ||
|
yosefe marked this conversation as resolved.
Resolved
|
||
| int *netmask_len_p) | ||
| { | ||
| ucs_netlink_route_info_t info = { | ||
| .if_index = if_index, | ||
| .sa_remote = sa_remote, | ||
| .netmask_len = -1 | ||
| }; | ||
|
|
||
| ucs_netlink_lookup_route(&info); | ||
|
|
||
| return info.found; | ||
| if (netmask_len_p != NULL) { | ||
| *netmask_len_p = info.netmask_len; | ||
| } | ||
|
|
||
| return (info.netmask_len > -1); | ||
| } | ||
|
|
||
| int ucs_netlink_is_best_route(int if_index, const struct sockaddr *sa_remote) | ||
| { | ||
| int netmask_len; | ||
|
|
||
| if (!ucs_netlink_route_exists(if_index, sa_remote, &netmask_len)) { | ||
| return 0; | ||
| } | ||
|
|
||
| return (ucs_netlink_max_netmask_len(sa_remote) == netmask_len); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -139,11 +139,6 @@ static ucs_status_t uct_tcp_iface_get_device_address(uct_iface_h tl_iface, | |
| dev_addr->flags = 0; | ||
| dev_addr->sa_family = saddr->sa_family; | ||
|
|
||
| /* Default gateway is not relevant for IPoIB interfaces */ | ||
| if (!ucs_netif_is_ipoib(iface->if_name)) { | ||
| dev_addr->flags |= UCT_TCP_DEVICE_ADDR_FLAG_ALLOW_DEFAULT_GW; | ||
| } | ||
|
|
||
| if (ucs_sockaddr_is_inaddr_loopback(saddr)) { | ||
| dev_addr->flags |= UCT_TCP_DEVICE_ADDR_FLAG_LOOPBACK; | ||
| memset(pack_ptr, 0, sizeof(uct_iface_local_addr_ns_t)); | ||
|
|
@@ -211,7 +206,6 @@ uct_tcp_iface_is_reachable_v2(const uct_iface_h tl_iface, | |
| struct sockaddr_storage remote_addr; | ||
| char remote_addr_str[UCS_SOCKADDR_STRING_LEN]; | ||
| unsigned ndev_index; | ||
| int allow_default_gw; | ||
| ucs_status_t status; | ||
|
|
||
| if (!uct_iface_is_reachable_params_valid( | ||
|
|
@@ -270,19 +264,20 @@ uct_tcp_iface_is_reachable_v2(const uct_iface_h tl_iface, | |
| return 0; | ||
| } | ||
|
|
||
| allow_default_gw = !!(tcp_dev_addr->flags & | ||
| UCT_TCP_DEVICE_ADDR_FLAG_ALLOW_DEFAULT_GW); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can we remove UCT_TCP_DEVICE_ADDR_FLAG_ALLOW_DEFAULT_GW flag and related logic? |
||
|
|
||
| if (!ucs_netlink_route_exists(ndev_index, | ||
| (const struct sockaddr *)&remote_addr, | ||
| allow_default_gw)) { | ||
| if (!ucs_netlink_is_best_route(ndev_index, | ||
| (const struct sockaddr*)&remote_addr)) { | ||
| uct_iface_fill_info_str_buf( | ||
| params, "no route to %s", | ||
| ucs_sockaddr_str((const struct sockaddr *)&remote_addr, | ||
| remote_addr_str, UCS_SOCKADDR_STRING_LEN)); | ||
| return 0; | ||
| } | ||
|
|
||
| /* This interface has the best route */ | ||
| ucs_trace("tcp_iface %p (%s): this interface has the best route to %s", | ||
| iface, iface->if_name, | ||
| ucs_sockaddr_str((const struct sockaddr*)&remote_addr, | ||
| remote_addr_str, UCS_SOCKADDR_STRING_LEN)); | ||
| return 1; | ||
| } | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.