]> exis.tech > repos - linux.git/commitdiff
IB/mad: Drop unmatched RMPP responses before reassembly
authorMichael Bommarito <michael.bommarito@gmail.com>
Sat, 6 Jun 2026 20:01:55 +0000 (16:01 -0400)
committerLeon Romanovsky <leon@kernel.org>
Mon, 29 Jun 2026 12:08:59 +0000 (08:08 -0400)
Kernel-handled RMPP receive processing starts reassembly for active
DATA responses before the response is matched to an outstanding send.
The normal match happens later, after ib_process_rmpp_recv_wc() has
either assembled a complete message or consumed the segment.

That ordering lets an unsolicited response that routes to a kernel
RMPP agent by the high TID bits allocate or extend RMPP receive state
before the full TID and source address are checked against a real
request. A reordered burst can therefore reach the receive-side
insertion path even though the response would not match any send.

For kernel-handled RMPP DATA responses, require the existing
ib_find_send_mad() match before entering RMPP reassembly. The matcher
already checks the full TID, management class and source address/GID
against the agent wait, backlog and in-flight send lists. If there is
no match, drop the response without creating RMPP state.

This leaves the RMPP window behavior unchanged and only rejects
responses that have no corresponding request.

Fixes: fa619a77046b ("[PATCH] IB: Add RMPP implementation")
Assisted-by: Codex:gpt-5-5-xhigh
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
Link: https://patch.msgid.link/3170ff3bc389a930bb1641f2caa394a0b2241579.1780774907.git.michael.bommarito@gmail.com
Signed-off-by: Leon Romanovsky <leon@kernel.org>
drivers/infiniband/core/mad.c

index 8d19613179e3eebda79cc15a31e13301274d90ee..e0b3b36b8b1496550e3ef22a31e9f04173778cff 100644 (file)
@@ -2031,6 +2031,24 @@ void ib_mark_mad_done(struct ib_mad_send_wr_private *mad_send_wr)
                change_mad_state(mad_send_wr, IB_MAD_STATE_EARLY_RESP);
 }
 
+static bool is_kernel_rmpp_data_response(struct ib_mad_agent_private *agent,
+                                        struct ib_mad_recv_wc *mad_recv_wc)
+{
+       const struct ib_mad_hdr *mad_hdr = &mad_recv_wc->recv_buf.mad->mad_hdr;
+       struct ib_rmpp_mad *rmpp_mad;
+
+       if (!ib_mad_kernel_rmpp_agent(&agent->agent) ||
+           !ib_response_mad(mad_hdr) ||
+           !ib_is_mad_class_rmpp(mad_hdr->mgmt_class))
+               return false;
+
+       rmpp_mad = (struct ib_rmpp_mad *)mad_recv_wc->recv_buf.mad;
+
+       return (ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) &
+               IB_MGMT_RMPP_FLAG_ACTIVE) &&
+              rmpp_mad->rmpp_hdr.rmpp_type == IB_MGMT_RMPP_TYPE_DATA;
+}
+
 static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv,
                                 struct ib_mad_recv_wc *mad_recv_wc)
 {
@@ -2050,6 +2068,18 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv,
        }
 
        list_add(&mad_recv_wc->recv_buf.list, &mad_recv_wc->rmpp_list);
+       if (is_kernel_rmpp_data_response(mad_agent_priv, mad_recv_wc)) {
+               spin_lock_irqsave(&mad_agent_priv->lock, flags);
+               mad_send_wr = ib_find_send_mad(mad_agent_priv, mad_recv_wc);
+               spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
+
+               if (!mad_send_wr) {
+                       ib_free_recv_mad(mad_recv_wc);
+                       deref_mad_agent(mad_agent_priv);
+                       return;
+               }
+       }
+
        if (ib_mad_kernel_rmpp_agent(&mad_agent_priv->agent)) {
                mad_recv_wc = ib_process_rmpp_recv_wc(mad_agent_priv,
                                                      mad_recv_wc);