Where: src/main/java/org/metricshub/ipmi/core/connection/queue/MessageQueue.java (getSequenceNumber()), MessageHandler.sendMessage() with isOneWay = true, IpmiConnector.sendOneWayMessage().
What happens: a one-way IPMI message takes a sequence number that is not reserved: nothing frees it, so nothing holds it either. If the BMC nevertheless replies to that message and the reply is delayed while the 63-value sequence space wraps (63 later allocations), the tag can belong to a newer queued request by then. #148 makes IpmiMessageHandler drop such a reply when it does not answer the command and network function of the queued request, which covers the keep-alive case and any one-way command different from the queued one. Two generations of the same command (a one-way Get Device ID followed, 63 allocations later, by a queued Get Device ID) cannot be told apart: the stale reply is reported as the newer request's result and the request is removed from the queue, so its real reply is dropped as an orphan.
Pre-existing behavior (the Verax library allocated one-way tags the same way); not reproduced on a BMC. sendOneWayMessage() is documented as not expecting a reply, and the library's only one-way IPMI command, the keep-alive, is queued as a marked request since #148.
Suggested fix: reserve the tag of a one-way message for the message timeout (a (tag, expiry) list in MessageQueue that isReserved() consults and the timer purges), or queue one-way messages as silent requests like Connection.KeepAlive. Either throttles callers that send many one-way messages (SOL data goes through its own SolMessageHandler queue), which is why it is not part of #148.
Found by the Codex review of #148.
Where:
src/main/java/org/metricshub/ipmi/core/connection/queue/MessageQueue.java(getSequenceNumber()),MessageHandler.sendMessage()withisOneWay = true,IpmiConnector.sendOneWayMessage().What happens: a one-way IPMI message takes a sequence number that is not reserved: nothing frees it, so nothing holds it either. If the BMC nevertheless replies to that message and the reply is delayed while the 63-value sequence space wraps (63 later allocations), the tag can belong to a newer queued request by then. #148 makes
IpmiMessageHandlerdrop such a reply when it does not answer the command and network function of the queued request, which covers the keep-alive case and any one-way command different from the queued one. Two generations of the same command (a one-wayGet Device IDfollowed, 63 allocations later, by a queuedGet Device ID) cannot be told apart: the stale reply is reported as the newer request's result and the request is removed from the queue, so its real reply is dropped as an orphan.Pre-existing behavior (the Verax library allocated one-way tags the same way); not reproduced on a BMC.
sendOneWayMessage()is documented as not expecting a reply, and the library's only one-way IPMI command, the keep-alive, is queued as a marked request since #148.Suggested fix: reserve the tag of a one-way message for the message timeout (a
(tag, expiry)list inMessageQueuethatisReserved()consults and the timer purges), or queue one-way messages as silent requests likeConnection.KeepAlive. Either throttles callers that send many one-way messages (SOL data goes through its ownSolMessageHandlerqueue), which is why it is not part of #148.Found by the Codex review of #148.