drivers/infiniband/core/mad_rmpp.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
find_seg_location() inserts reordered RMPP DATA segments into a
per-transaction list by walking that list in reverse. The walk runs
under rmpp_recv->lock in the MAD receive worker, so a large receive
window makes a reversed RMPP burst expensive.
The receive window comes from recv_queue.max_active. With the default
recv_queue_size of 512, the window is 64. Larger tuned queues can raise
the window to 1024, turning one reordered transaction into repeated
long list walks and keeping the target port's MAD worker busy for
milliseconds.
Cap the RMPP window at 64, matching the current default. This keeps
existing behavior for default configurations and prevents larger receive
queues from increasing the worst-case insertion walk.
Fixes: fa619a77046b ("[PATCH] IB: Add RMPP implementation")
Cc: stable@vger.kernel.org
Assisted-by: Codex:gpt-5-5-xhigh
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
---
Impact: a fabric peer that can send QP1 GMP RMPP DATA segments can keep
the targeted port's MAD worker busy with reordered RMPP bursts, delaying
other MAD processing on that port.
I tested this on v7.1-rc2 under x86_64 QEMU/KVM with rxe and raw RoCEv2
packets carrying descending RMPP segment numbers. With
recv_queue_size=8192, the unpatched kernel spent at least 1.5 ms per
F=1024 burst in the insertion walk; the patched kernel dropped the same
run to about 0.28 ms because segments outside the capped window are
rejected before the list grows. A normal in-window F=32 RMPP exchange
still completed; there are no in-tree selftests for QP1 GMP RMPP
reassembly in tools/testing/selftests/drivers/net/rdma.
Changes in v2:
- Rewrite the commit message in shorter, plain language.
- Trim the code comment to the local reason for the cap.
drivers/infiniband/core/mad_rmpp.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/drivers/infiniband/core/mad_rmpp.c b/drivers/infiniband/core/mad_rmpp.c
index 17c4c52a19e4c..0db645eb2e29b 100644
--- a/drivers/infiniband/core/mad_rmpp.c
+++ b/drivers/infiniband/core/mad_rmpp.c
@@ -391,9 +391,18 @@ static inline struct ib_mad_recv_buf *get_next_seg(struct list_head *rmpp_list,
return container_of(seg->list.next, struct ib_mad_recv_buf, list);
}
+/*
+ * find_seg_location() is linear in the number of queued segments.
+ * Keep the RMPP window at the default size so a larger receive queue
+ * does not also enlarge the reordered DATA insertion walk.
+ */
+#define IB_MAD_RMPP_MAX_WINDOW 64
+
static inline int window_size(struct ib_mad_agent_private *agent)
{
- return max(agent->qp_info->recv_queue.max_active >> 3, 1);
+ int wsize = agent->qp_info->recv_queue.max_active >> 3;
+
+ return clamp(wsize, 1, IB_MAD_RMPP_MAX_WINDOW);
}
static struct ib_mad_recv_buf *find_seg_location(struct list_head *rmpp_list,
--
2.53.0
© 2016 - 2026 Red Hat, Inc.