Skip to content

UCT/IB/GDAKI: Relax RoCE route check for GPU-associated NICs - #11835

Open
amastbaum wants to merge 4 commits into
openucx:masterfrom
amastbaum:fix/rc-gda-reachability
Open

UCT/IB/GDAKI: Relax RoCE route check for GPU-associated NICs#11835
amastbaum wants to merge 4 commits into
openucx:masterfrom
amastbaum:fix/rc-gda-reachability

Conversation

@amastbaum

Copy link
Copy Markdown
Contributor

What?

Allow rc_gda to use a valid route through its GPU-associated NIC even when another NIC has a more-specific route.

Why?

The regular best-route check can select a NIC associated with another GPU and incorrectly mark rc_gda as unreachable.

How?

For GDAKI interfaces, add a route check that accepts any matching non-default route, while allowing a default route only as a fallback if no other rules exist for this destination.

@svc-nvidia-pr-review

Copy link
Copy Markdown

🤖 Starting review — findings will be posted here when done.

Comment thread src/ucs/sys/netlink.c Outdated
return (info.netmask_len > -1);
}

int ucs_netlink_route_exists_with_default_fallback(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This adds a new public API (ucs_netlink_route_exists_with_default_fallback) and a new reachability branch, but there is no unit test for netlink route logic in test/gtest/ucs/, and no CI job exercises the relaxed path. The default-vs-specific fallback decision is the whole point of the change and is easy to get subtly wrong. can we add a focused test for the default-fallback logic (specific route accepted regardless of other ifaces; default-only route rejected when another iface has a more-specific route)? there's currently no netlink route test to catch a regression here. If a hermetic test isn't practical (netlink needs a real routing table), it's worth the author explaining the coverage gap.

Comment thread src/ucs/sys/netlink.h Outdated
int ucs_netlink_route_exists(int if_index, const struct sockaddr *sa_remote,
int *netmask_len_p);

/**

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor: the @return line says "1 if such a route exists ... 0 otherwise", but a default route through this iface can still return 0 because another interface has a more-specific route. The body text is accurate; only the @return line slightly overstates. Maybe reword to match the body ("1 if the route is accepted under the default-fallback rule").

@amastbaum
amastbaum requested review from rakhmets and tvegas1 August 26, 2026 11:05
Comment thread src/uct/ib/base/ib_iface.c Outdated
ucs_debug("%s", ucs_string_buffer_cstr(&info));
}

static int uct_ib_iface_roce_ndev_has_route(uct_ib_iface_t *iface,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we unify both cases like below? this could replace netlink is best route function.

int ucs_netlink_route_matches(int if_index, const struct sockaddr *sa_remote,
                              int relaxed_check)
{
    int netmask_len;

    /* No route to the destination through this interface, not even a
     * default one */
    if (!ucs_netlink_route_exists(if_index, sa_remote, &netmask_len)) {
        return 0;
    }

    /* Relaxed mode: accept a non-default route unconditionally */
    if (relaxed_check && (netmask_len > 0)) {
        return 1;
    }

    /* Best route overall; a default route qualifies only as a fallback */
    return ucs_netlink_max_netmask_len(sa_remote) == netmask_len;
}

Comment thread src/uct/ib/base/ib_iface.c Outdated
uct_ib_iface_set_path_mtu(self, config);

self->config.send_overhead = config->send_overhead;
self->config.relaxed_route_check =

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe roce_relaxed_route_check since it is specific?

Comment thread src/uct/ib/base/ib_iface.h Outdated
UCT_IB_DDP_SUPPORTED = UCS_BIT(3)
UCT_IB_DDP_SUPPORTED = UCS_BIT(3),

/* Whether to accept a specific route through the current NIC even when

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

accept any non-default route, accept default route if no best?

Comment thread src/uct/ib/mlx5/gdaki/gdaki.c Outdated
init_attr.qp_type = IBV_QPT_RC;
init_attr.dev_name = ib_name;
init_attr.max_rd_atomic = IBV_DEV_ATTR(&md->super.dev, max_qp_rd_atom);
/* A better route through a NIC associated with another GPU does not make

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need to comment here

Comment thread src/uct/ib/base/ib_iface.c Outdated
ucs_debug("%s", ucs_string_buffer_cstr(&info));
}

static int uct_ib_iface_roce_ndev_has_route(uct_ib_iface_t *iface,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we add gtest for relaxed and non-relaxed?

@yosefe yosefe left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO need to see why default GW logic ins not good enough, i'd expect the logic to be the same eventually for GDA and non-GDA

@amastbaum

Copy link
Copy Markdown
Contributor Author

IMO need to see why default GW logic ins not good enough, i'd expect the logic to be the same eventually for GDA and non-GDA

@yosefe I agree that the logic should be the same for GDA and non-GDA RoCE.
This was actually the initial implementation in #11033, to accept a specific route and use the default gateway only as a fallback.
I think this relaxed check should work for both GDA and non-GDA RoCE, but for TCP we should still keep the current best-route check because Linux will use the best matching route.

@svc-nvidia-pr-review

Copy link
Copy Markdown

🤖 Starting review — findings will be posted here when done.

init_attr.seg_size = config->super.super.seg_size;
init_attr.qp_type = IBV_QPT_RC;
init_attr.dev_name = ib_name;
init_attr.max_rd_atomic = IBV_DEV_ATTR(&md->super.dev, max_qp_rd_atom);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor: this blank-line removal is unrelated to the route-matching change, pls drop it from this PR.

Comment thread src/uct/ib/base/ib_iface.c Outdated

if (ucs_netlink_is_best_route(ndev_index, sa_remote)) {
/* This interface has the best route */
if (ucs_netlink_route_matches(ndev_index, sa_remote, 1)) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we use a named constant/enum instead of a bare 1 here? ..., 1) is opaque at the call site vs the 0 used by the tcp caller.

@svc-nvidia-pr-review

Copy link
Copy Markdown

is the new relaxed RoCE reachability path covered by an existing CI job, or can we add a focused test? there's no unit test for the netlink route matching today.

Comment thread src/ucs/sys/netlink.c
{
int netmask_len;

if (!ucs_netlink_route_exists(if_index, sa_remote, &netmask_len)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think it could help to add comments for each three step, mentioning the logic

Comment thread src/uct/tcp/tcp_iface.c Outdated
if (!ucs_netlink_is_best_route(ndev_index,
(const struct sockaddr*)&remote_addr)) {
if (!ucs_netlink_route_matches(ndev_index,
(const struct sockaddr*)&remote_addr, 0)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i tend to agree here with relaxed=0 for keeping best route scheme since anyway kernel is going to pick best route (with or without src addr bind / configurable) so we try to make ucx understand that it uses the best interface as a lane.

Comment thread src/ucs/sys/netlink.h Outdated
* @param [in] if_index Network interface index.
* @param [in] sa_remote Pointer to the destination address.
* @param [in] relaxed_check If nonzero, accept any non-default route and
* accept a default route only if no better route

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe: When set, accept any non-default route, or a default route if nothing better exists. Otherwise, accept only the best route.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe: When set, accept any route. Otherwise accept only best route.

@svc-nvidia-pr-review

Copy link
Copy Markdown

🤖 Starting review — findings will be posted here when done.

@svc-nvidia-pr-review

Copy link
Copy Markdown

🤖 Review complete — no issues found.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants