Repository navigation
UCT: prioritize routes with longer subnet masks in the reachability check - #11033
Conversation
| int ucs_netlink_route_exists(int if_index, const struct sockaddr *sa_remote, | ||
| int allow_default_gw); | ||
| int *has_default_gw_p); |
There was a problem hiding this comment.
Currently the information about default gw rules is retrieved implicitly via the out parameter but I can create a separate function for that.
133dd3e to
379c114
Compare
|
| * interface, as assigned by the system | ||
| * (e.g., obtained via if_nametoindex()). | ||
| * @param [in] sa_remote Pointer to the destination address. | ||
| * @param [out] has_default_gw_p Optional pointer to store whether a default |
There was a problem hiding this comment.
wdyt of: instead of returning 0/1 and an optional _p, have a single return value with an enum like {None,Route,Gateway} (roughly)?
| int *has_default_gw_p); | ||
|
|
||
| /** | ||
| * Check whether a specific route exists for a given destination address |
There was a problem hiding this comment.
Where does the word "specific" come from? Is it used in netlink terminology?
There was a problem hiding this comment.
So not really. It's only relative to the "default GW/route" term. I need to emphasize their difference (can also be "non-default route")
| return 1; | ||
| /* No route found at all */ | ||
| if (lo_status == UCS_OK) { | ||
| uct_iface_fill_info_str_buf(params, |
There was a problem hiding this comment.
Can eliminate code duplication here?
| return 1; | ||
| } | ||
|
|
||
| /* Going to search for a default GW route on this interface. If found, and |
There was a problem hiding this comment.
Please move to lines 286-293 block, make more concise (w/o "going to..", only explain the reasoning)
| UCT_IB_IFACE_ARG(iface), | ||
| ndev_index, lo_ndev_index); | ||
| return 0; | ||
| /* Going to search a default GW route on this interface. If found, and |
There was a problem hiding this comment.
This comment appears twice.
There was a problem hiding this comment.
@gleon99 It appears once in tcp_iface.c and once in ib_iface.c.
You mean to eliminate duplications between them? Maybe need some ip category, or tcp_iface.c is enough?
|
should we prioritize routes by subnet prefix length in general (i.e longest prefix matching), not just for default gw? |
| int ucs_netlink_has_any_specific_route(const struct sockaddr *sa_remote) | ||
| { | ||
| ucs_netlink_rt_rules_t iface_rules; | ||
| ucs_netlink_route_info_t info = {.sa_remote = sa_remote}; |
There was a problem hiding this comment.
| ucs_netlink_route_info_t info = {.sa_remote = sa_remote}; | |
| ucs_netlink_route_info_t info = { | |
| .sa_remote = sa_remote, | |
| .found = 0, | |
| .found_default_gw = 0 | |
| }; |
| ucs_netlink_route_info_t info = {.if_index = if_index, | ||
| .sa_remote = sa_remote}; |
There was a problem hiding this comment.
initialize found_defualt_gw to 0
| /** | ||
| * Check whether a specific route exists for a given destination address | ||
| * in ANY network interface. | ||
| * | ||
| * @param [in] sa_remote Pointer to the destination address. | ||
| * | ||
| * @return 1 if a specific route exists in any interface, or 0 otherwise. | ||
| */ | ||
| int ucs_netlink_has_any_specific_route(const struct sockaddr *sa_remote); |
There was a problem hiding this comment.
| /** | |
| * Check whether a specific route exists for a given destination address | |
| * in ANY network interface. | |
| * | |
| * @param [in] sa_remote Pointer to the destination address. | |
| * | |
| * @return 1 if a specific route exists in any interface, or 0 otherwise. | |
| */ | |
| int ucs_netlink_has_any_specific_route(const struct sockaddr *sa_remote); | |
| /** | |
| * Check whether a non-default route exists for a given destination address | |
| * in ANY network interface. | |
| * | |
| * @param [in] sa_remote Pointer to the destination address. | |
| * | |
| * @return 1 if a non-default route exists in any interface, or 0 otherwise. | |
| */ | |
| int ucs_netlink_has_non_default_route(const struct sockaddr *sa_remote); |
| uct_iface_fill_info_str_buf(params, | ||
| "loopback iface index is not found"); | ||
| return 0; | ||
| if (ucs_netlink_route_exists(ndev_index, sa_remote, &has_default_gw)) { |
There was a problem hiding this comment.
has_default_gw is not used, so it would be a bit cleaner to use an enum as a return type like @gleon99 suggested
|
This PR might solve #11035? |
yosefe
left a comment
There was a problem hiding this comment.
If it is not trivial to fix the review comments, pls submit a PR to workaround the failing CI test in meantime, or push this PR as is and then rework/revert it
| /* No route found - first, try loopback interface for reachability | ||
| * check, because it may be used for routing in case of an interface with | ||
| * VRF is configured and a RoCE IP interface uses this VRF table for | ||
| * routing. */ | ||
| if (uct_ib_iface_get_loopback_ndev_index(&lo_ndev_index) == UCS_OK) { |
There was a problem hiding this comment.
BTW, shouldn't VRF be inside "netlink" code because it is also relevant for TCP?
1bd31fa to
37bcdb7
Compare
|
|
||
| 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) |
There was a problem hiding this comment.
I could actually leave it as before and only trigger the cache initialization from ucs_netlink_route_exists, because ucs_netlink_route_exists is eventually called from ucs_netlink_is_best_route as well.
I just wasn't sure what is the best way to initialize the cache because I want to promise it will be triggered from each api call, and it's currently done quite implicitly. @yosefe @gleon99
There was a problem hiding this comment.
Maybe init the cache in ucs_netlink_lookup_route?
| info.sa_remote = sa_remote; | ||
| info.found = 0; | ||
| info.allow_default_gw = allow_default_gw; | ||
| static int ucs_netlink_has_better_route(const struct sockaddr *sa_remote, |
There was a problem hiding this comment.
maybe return the longest matching netmask length (-1 if not found)?
There was a problem hiding this comment.
So we should rename this function to ucs_netlink_max_netmask_len
| } | ||
|
|
||
| allow_default_gw = !!(tcp_dev_addr->flags & | ||
| UCT_TCP_DEVICE_ADDR_FLAG_ALLOW_DEFAULT_GW); |
There was a problem hiding this comment.
can we remove UCT_TCP_DEVICE_ADDR_FLAG_ALLOW_DEFAULT_GW flag and related logic?
| int ucs_netlink_is_this_the_route(int if_index, | ||
| const struct sockaddr *sa_remote); |
There was a problem hiding this comment.
@yosefe This is outdated, currently called ucs_netlink_is_best_route.
preferred is better?
| int found; | ||
| int allow_default_gw; /* Allow matching default | ||
| gateway routes */ | ||
| int found_netmask_len; |
There was a problem hiding this comment.
Or maybe just
| int found_netmask_len; | |
| int netmask_len; |
|
|
||
| ucs_array_for_each(curr_entry, iface_rules) { | ||
| if (curr_entry->subnet_prefix_len > info->found_netmask_len && | ||
| if (curr_entry->subnet_prefix_len > found_netmask_len && |
| ucs_netlink_route_info_t info = {.if_index = if_index, | ||
| .sa_remote = sa_remote, | ||
| .netmask_len = -1}; |
There was a problem hiding this comment.
Minor: formatting
| ucs_netlink_route_info_t info = {.if_index = if_index, | |
| .sa_remote = sa_remote, | |
| .netmask_len = -1}; | |
| ucs_netlink_route_info_t info = { | |
| .if_index = if_index, | |
| .sa_remote = sa_remote, | |
| .netmask_len = -1 | |
| }; |
It seems that there are multiple clang-format issues
check git-clang-format --diff HEAD~13
Other than that, it's approved on my side
| } | ||
| }); | ||
| }) | ||
| ; |
|
@amastbaum please squash |
e67e15b to
9cce62c
Compare
What?
Use a default GW routes only when no specific routes exist.
Found in a CI issue when running
./test/gtest/gtest --gtest_filter=*all/test_ucp_sockaddr_protocols_diff_net_devices.restricted_net_devices/0*