UCP/WIREUP: Add a token trailer and an ACK message to the lane address exchange - #11843
UCP/WIREUP: Add a token trailer and an ACK message to the lane address exchange#11843evgeny-leksikov wants to merge 3 commits into
Conversation
|
🤖 Starting review — findings will be posted here when done. |
| /* number of retries left before giving up */ | ||
| unsigned retries_left; | ||
| uint8_t state; | ||
| /* Generation of the LANES_ADDR exchange, incremented by every request and |
There was a problem hiding this comment.
The comment states request_id exists 'so that answers of an older round are recognized', but nothing compares the received request_id against the stored one; stale-reply recognition is not actually implemented.
| } | ||
|
|
||
| tokens_info->request_id = info->request_id; | ||
| tokens_info->address_length = address_length; |
There was a problem hiding this comment.
Minor: address_length narrowing. tokens_info->address_length is uint32_t but assigned from size_t address_length. Not a practical issue, but a latent narrowing worth a comment or ucs_assert.
…s exchange Append an optional trailer to the LANES_ADDR messages, holding the generation of the recovery round and a token section per direction: the TX tokens of the lanes the message provides, and the RX tokens of the lanes it answers. Both sections carry one length per lane and are empty until the lanes provide tokens, which lands in a follow-up patch together with their consumer, as does matching the generation against the tokens of an answer. Add LANES_ADDR_ACK, the third leg the exchange needs so that the peer which replies also receives the tokens derived from its own. The trailer is sent only towards peers of UCP_WIREUP_ADDR_TOKEN_MIN_DST_VERSION and above, and the ACK, which exists only to carry it, is withheld from older peers.
The token sections are parsed ahead of the packed addresses, so a malformed section must be rejected rather than shift the addresses. Feed crafted sections to the parser, including truncated ones, which the empty sections of the wire itself do not exercise.
9370791 to
a4d85e4
Compare
|
🤖 Starting review — findings will be posted here when done. |
| * Minimal peer release version which understands the token trailer of the | ||
| * LANES_ADDR messages. Older peers get the messages without any token. | ||
| */ | ||
| #define UCP_WIREUP_ADDR_TOKEN_MIN_DST_VERSION 23 |
There was a problem hiding this comment.
UCP_WIREUP_ADDR_TOKEN_MIN_DST_VERSION is 23 but ucx_ver_minor is 24. If a released v23 peer already understands LANES_ADDR without the trailer, gating at >= 23 makes us append a trailer it can't parse and it will unpack the addresses from the wrong offset. Should this be 24 (the first version that adds the trailer)?
| @@ -2459,3 +2459,58 @@ UCS_TEST_P(test_ucp_reconfig_connect_remote, put_canceled) | |||
| } | |||
There was a problem hiding this comment.
Coverage note: The gtest (test_ucp_wireup_token_section) only exercises ucp_wireup_skip_token_section in isolation. There is no end-to-end test that a v24<->v24 recovery exchange round-trips the trailer, nor a mixed-version test confirming an older peer still parses a trailer-less LANES_ADDR. The mixed-version path is the one the version gate above protects, so if practical it would be worth confirming via an existing recovery/fault-tolerance job.
|
🤖 CI Triage Agent — TL;DR: The Full analysisSummary: Root cause: In The code is functionally correct — Note the helper also has a real (though currently unreachable) hazard that reinforces the warning: the truncation check at wireup.c:1251–1255 returns Implicated commit: File: Suggested fix: Initialize the pointer at its declaration so no code path can leave it indeterminate: const ucp_wireup_msg_lanes_info_t *lanes_info = NULL;This is a one-line, zero-cost change that silences the diagnostic on every compiler without restructuring the control flow. Two recommended hardening follow-ups in the same patch:
Avoid "fixing" this by dropping Related: PR #11843 (this build). Prior work in the same series that introduced the LANES_ADDR exchange and its handlers:
|
Master bumped UCP_API_MINOR to 24. A gate of 23 would send the trailer to peers that still parse addresses immediately after lanes_info. Keep the original meaning of the LANES_ADDR lane maps in comments, and drop the claim that the trailer carries a length of its own.
|
🤖 Starting review — findings will be posted here when done. |
| address_ptr = UCS_PTR_TYPE_OFFSET(address_ptr, | ||
| ucp_wireup_msg_lanes_info_t); | ||
| if (ucp_wireup_msg_is_lanes_addr(msg->type)) { | ||
| ucs_assert(ep != NULL); |
There was a problem hiding this comment.
(minor) The ucs_assert(ep != NULL) moved earlier, dropping the msg->dst_ep_id != UCS_PTR_MAP_KEY_INVALID check. The per-type branches previously asserted this; now the only guard before ucp_wireup_parse_lanes_addr(ep, ...) dereferences ep is ucs_assert(ep != NULL). Release-build behavior is unchanged (ep was already dereferenced downstream), so not a regression, just slightly weaker validation. Fine to leave as is.
|
(question) Trailer presence relies on symmetric dst_version: both peers independently decide whether the token trailer is present using their own ucp_ep_config(ep)->key.dst_version (ucp_wireup_ep_supports_tokens). If the two ends hold asymmetric config views of the peer release version, the sender may add a trailer the receiver doesn't expect (or vice versa), causing the receiver to drop the message or misparse addresses. For recovery both directions are established, so dst_version should be consistent — but please confirm key.dst_version is guaranteed symmetric on both peers when LANES_ADDR messages flow. If yes, a note in the parse function would help; if not, this could silently stall recovery. No test/coverage gap for the parser itself; the runtime path (real recovery with tokens-capable peers exchanging ACKs) is exercised only by the existing recovery/fault-tolerance suites — worth confirming one of those runs with dst_version >= 24 peers so the ACK path is actually hit, since the trailer is version-gated. |
|
🤖 CI Triage Agent — TL;DR: The aarch64 java11 job failed in the "Build UCX" step, not in any Java test: Full analysisSummary: Root cause: In This is a new-code regression from the PR itself: the refactor that moved lanes-info parsing into Implicated commit: File: Suggested fix: Initialize the pointer at its declaration so the definite-assignment analysis is trivially satisfied: const ucp_wireup_msg_lanes_info_t *lanes_info = NULL;Optionally add Related: PR #11843 (#11843) — the failure is self-contained in this PR; no pre-existing issue found.
|
What?
Append an optional token trailer to the
LANES_ADDRwireup messages and add theLANES_ADDR_ACKmessage which closes the exchange. The trailer is framing only:its token sections are present but empty, and no token is queried or consumed yet.
Why?
Groundwork for hardware PSN fault tolerance. Purging a failed UCT lane requires the
PSN tokens of both directions, which have to travel with the lane addresses that
recovery already re-exchanges. Splitting the wire format out of the feature keeps the
protocol change reviewable on its own and lets the token query, per-lane storage and
their consumer land in a follow-up.
How?
Recovery today is a two-legged exchange over the AM lane. The endpoint which detects
a lane failure sends
LANES_ADDR_REQUEST, packing the addresses of the lanes itrebuilt in
provided_lane_map; the peer replies withLANES_ADDR_REPLY, packing theaddresses of the lanes it managed to rebuild in turn.
The trailer goes between the fixed
ucp_wireup_msg_lanes_info_t, which UCX 1.22already ships, and the packed addresses:
Each token section holds one length byte per lane followed by the tokens themselves,
so a lane which has no token costs one zero byte. The sections take their lanes from
the maps already in
lanes_inforather than from maps of their own: the TX sectionbelongs to
provided_lane_map, the lanes the message carries addresses for, and theRX section to
requested_lane_map, redefined as the lanes the message answers. Theaddresses stay last, so they need no length of their own.
Both peers decide on the trailer from the peer release version in
ucp_ep_config_key_t::dst_version, gated byUCP_WIREUP_ADDR_TOKEN_MIN_DST_VERSION,so nothing is added to the fixed header and older peers keep parsing the addresses
where they are today.
request_idcarries the recovery generation, echoed by thepeer, for the follow-up to tell answers of different rounds apart.
Why a third leg: an RX token is derived from the TX token of the remote side, so
each peer can only produce the RX tokens of the other one. The request carries the
initiator's TX tokens, and the reply carries both the responder's TX tokens and the
RX tokens it derived for the initiator. Nothing has yet delivered the RX tokens the
initiator derives from the reply, which is what
LANES_ADDR_ACKis for. It existsonly to carry the trailer, so it is withheld from peers below the minimum version.
Testing: gtest coverage of the section parser, including truncated sections which the
empty sections of the wire itself never produce, plus the fault-tolerance suite on
ConnectX-7 (
test_ucp_fault_toleranceandtest_ucp_wireup, no failures).