UCT/IB/MLX5: Non-DevX rc_mlx5 CQ notification misses after Direct Verbs polling
Describe the bug
In the non-DevX rc_mlx5 transport, the CQ is polled through the mlx5 Direct Verbs path but armed through the generic verbs notification path.
The Direct Verbs polling path advances the consumer index maintained by UCX (uct_ib_mlx5_cq_t::cq_ci). However, the non-DevX arm path calls ibv_req_notify_cq(), which uses the consumer index maintained internally by the provider/libibverbs path.
These two consumer-index states are not synchronized. As a result, a CQ event notification can be missed even though a CQE is already available.
This report is specific to the non-DevX rc_mlx5 path. The DevX CQ event path is not affected.
Steps to reproduce
Environment:
- UCX: upstream
master, commit e5fbdbb97
- OS: Rocky Linux 9
- Architecture: x86_64
- HCA: Mellanox ConnectX-4 Lx VF (
mlx5_0)
- Port:
mlx5_0:1
- Link layer: Ethernet/RoCE
- Firmware:
14.27.4062
UCX_IB_MLX5_DV=y
UCX_IB_MLX5_DEVX=n
UCX_TLS=rc_mlx5,ud_mlx5
UCX_NET_DEVICES=mlx5_0:1
Build:
./autogen.sh
CPPFLAGS=-D_GNU_SOURCE ./contrib/configure-devel --enable-debug --with-verbs --with-mlx5 --with-rdmacm --prefix=$PWD/install
make -j8
make -C test/gtest -j8
make -C src/tools/perf -j8
Run:
export UCX_TLS=rc_mlx5,ud_mlx5
export UCX_NET_DEVICES=mlx5_0:1
export UCX_IB_MLX5_DV=y
export UCX_IB_MLX5_DEVX=n
export UCX_RNDV_THRESH=0
export UCX_RNDV_SCHEME=get_zcopy
export UCX_WARN_UNUSED_ENV_VARS=n
export UCX_WAKEUP_PROBE_TIMEOUT_MS=10
./src/tools/perf/ucx_perftest -l -t ucp_get -s 1048576 -n 70000 -w 1000 -O 1 -T 1 -M single -c 20 -I -E sleep -f
The wakeup probe performs ucp_worker_progress(), ucp_worker_arm(),
poll(completion_fd, 10 ms), and then calls ucp_worker_progress() again
if poll times out. A timeout is productive when the final progress call
returns a non-zero value.
Observed behavior
Unmodified upstream result:
wakeup waits: 261419
completion fd ready: 259373
fd timeouts: 2046
productive timeouts: 2046
max UCX CQ CI: 9025270
On the tested device, the first stable miss was observed after the UCX CQ
consumer index crossed approximately 2^23 (8388608). The exact boundary
may depend on CQ size, hardware and provider details.
Root cause
The non-DevX path combines Direct Verbs polling with generic verbs arming:
rc_mlx5 progress -> Direct Verbs CQ poll -> UCX cq_ci advances
rc_mlx5 arm -> ibv_req_notify_cq() -> provider CQ CI is used
The poll and arm operations use different CQ consumer-index owners. The mlx5
CQ ARM doorbell must use the consumer index maintained by the same Direct
Verbs implementation that performs polling.
This is consistent with commit d68f347dad9afca677a1d88ea32a25529993ce6e,
UCT/DC/TEST: Fix DC arm to use uct_ib_mlx5dv_arm_cq(), which states that
ibv_req_notify_cq() is not appropriate when the mlx5 CQ consumer index is
not updated through the generic verbs path.
Proposed fix
For non-DevX rc_mlx5:
- Keep
uct_ib_iface_pre_arm().
- Keep
uct_rc_iface_arm_cq_check() and UCS_ERR_BUSY handling.
- Arm each selected verbs CQ with
uct_ib_mlx5dv_arm_cq().
- Keep the DevX arm path unchanged.
if (md->flags & UCT_IB_MLX5_MD_FLAG_DEVX_CQ) {
return uct_rc_mlx5_iface_devx_arm(iface, events);
}
status = uct_ib_iface_pre_arm(&iface->super.super);
if (status != UCS_OK) {
return status;
}
dirs = uct_rc_iface_arm_cq_check(&iface->super, events, solicited);
ucs_for_each_bit(dir, dirs) {
uct_ib_mlx5dv_arm_cq(&iface->cq[dir], solicited[dir]);
}
return UCS_OK;
Validation of the proposed fix
Hardware regression:
rc_mlx5/test_uct_event_ib_non_devx.arm_uses_direct_cq_ci/*: 50/50 passed
rc_mlx5/test_uct_event_ib.tx_cq/0: passed
rc_mlx5/test_uct_event_ib.txrx_cq/0: passed
Standalone A/B results:
| Variant |
Max CQ CI |
FD timeouts |
Productive timeouts |
Generic ibv_req_notify_cq() arm |
9,025,270 |
2,046 |
2,046 |
uct_ib_mlx5dv_arm_cq() arm |
9,025,394 |
0 |
0 |
After applying the direct-arm change, the same workload crossed the same
consumer-index boundary with no productive wakeup timeout.
Additional information
The reproducer uses only UCX upstream source, UCX GTest, UCX ucx_perftest,
libibverbs/rdma-core and one mlx5 HCA. No application-specific framework,
storage system, filesystem or proprietary component is required.
The issue is a mismatch between CQ polling and CQ notification arming in
the non-DevX rc_mlx5 transport.
UCT/IB/MLX5: Non-DevX rc_mlx5 CQ notification misses after Direct Verbs polling
Describe the bug
In the non-DevX
rc_mlx5transport, the CQ is polled through the mlx5 Direct Verbs path but armed through the generic verbs notification path.The Direct Verbs polling path advances the consumer index maintained by UCX (
uct_ib_mlx5_cq_t::cq_ci). However, the non-DevX arm path callsibv_req_notify_cq(), which uses the consumer index maintained internally by the provider/libibverbs path.These two consumer-index states are not synchronized. As a result, a CQ event notification can be missed even though a CQE is already available.
This report is specific to the non-DevX
rc_mlx5path. The DevX CQ event path is not affected.Steps to reproduce
Environment:
master, commite5fbdbb97mlx5_0)mlx5_0:114.27.4062UCX_IB_MLX5_DV=yUCX_IB_MLX5_DEVX=nUCX_TLS=rc_mlx5,ud_mlx5UCX_NET_DEVICES=mlx5_0:1Build:
./autogen.sh CPPFLAGS=-D_GNU_SOURCE ./contrib/configure-devel --enable-debug --with-verbs --with-mlx5 --with-rdmacm --prefix=$PWD/install make -j8 make -C test/gtest -j8 make -C src/tools/perf -j8Run:
The wakeup probe performs
ucp_worker_progress(),ucp_worker_arm(),poll(completion_fd, 10 ms), and then callsucp_worker_progress()againif poll times out. A timeout is productive when the final progress call
returns a non-zero value.
Observed behavior
Unmodified upstream result:
On the tested device, the first stable miss was observed after the UCX CQ
consumer index crossed approximately
2^23(8388608). The exact boundarymay depend on CQ size, hardware and provider details.
Root cause
The non-DevX path combines Direct Verbs polling with generic verbs arming:
The poll and arm operations use different CQ consumer-index owners. The mlx5
CQ ARM doorbell must use the consumer index maintained by the same Direct
Verbs implementation that performs polling.
This is consistent with commit
d68f347dad9afca677a1d88ea32a25529993ce6e,UCT/DC/TEST: Fix DC arm to use uct_ib_mlx5dv_arm_cq(), which states thatibv_req_notify_cq()is not appropriate when the mlx5 CQ consumer index isnot updated through the generic verbs path.
Proposed fix
For non-DevX
rc_mlx5:uct_ib_iface_pre_arm().uct_rc_iface_arm_cq_check()andUCS_ERR_BUSYhandling.uct_ib_mlx5dv_arm_cq().Validation of the proposed fix
Hardware regression:
Standalone A/B results:
ibv_req_notify_cq()armuct_ib_mlx5dv_arm_cq()armAfter applying the direct-arm change, the same workload crossed the same
consumer-index boundary with no productive wakeup timeout.
Additional information
The reproducer uses only UCX upstream source, UCX GTest, UCX
ucx_perftest,libibverbs/rdma-core and one mlx5 HCA. No application-specific framework,
storage system, filesystem or proprietary component is required.
The issue is a mismatch between CQ polling and CQ notification arming in
the non-DevX
rc_mlx5transport.