transport: free un-wanted responses in pldm_transport_send_recv_msg()

mctp-demux broadcasts the PLDM response messages to all of mctp
socket instances. That means the GetSensorReading response from one
instance (pldmd) can be received by the other instance (pldmtool)
which is waiting for the response of GetPDR request message. When the
gap time between the two requests of pldmtool is long enough the
number of GetSensorReading response messages can be more than 32. That
means the instance ID of new GetPDR command in pldmtool can equal with
the used and free one in GetSensorReading. The
`pldm_transport_send_recv_msg()` will detect the reponse of
GetSensorReading as the response of the GetPDR request.

To prevent this unexpected behavior the `pldm_transport_send_recv_msg()`
should free the un-wanted responses before sending new PLDM request. The
serialised message to be sent must already encode an allocated instance
ID, which by the specification must not be reused before expiry.
Therefore after the socket is drained, any subsequent response
containing the request's instance ID must be the response matching the
request.

Signed-off-by: Thu Nguyen <thu@os.amperecomputing.com>
[AJ: Add a test, massage the commit message]
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
Change-Id: I6c684bdaea2ba5d96b24ecd3c72e846c644fb16d
diff --git a/src/transport/test.c b/src/transport/test.c
index 3d92111..0f35ffc 100644
--- a/src/transport/test.c
+++ b/src/transport/test.c
@@ -49,20 +49,33 @@
 
 	desc = &test->seq[test->cursor];
 
-	if (desc->type != PLDM_TRANSPORT_TEST_ELEMENT_LATENCY) {
-		return PLDM_REQUESTER_POLL_FAIL;
-	}
+	if (desc->type == PLDM_TRANSPORT_TEST_ELEMENT_LATENCY) {
+		rc = timerfd_settime(test->timerfd, 0, &desc->latency, NULL);
+		if (rc < 0) {
+			return PLDM_REQUESTER_POLL_FAIL;
+		}
 
-	rc = timerfd_settime(test->timerfd, 0, &desc->latency, NULL);
-	if (rc < 0) {
+		/* This was an explicit latency element, so now move beyond it for recv */
+		test->cursor++;
+	} else if (desc->type == PLDM_TRANSPORT_TEST_ELEMENT_MSG_RECV) {
+		/* Expire the timer immediately so it appears ready */
+		static const struct itimerspec ready = {
+			.it_value = { 0, 1 },
+			.it_interval = { 0, 0 },
+		};
+		rc = timerfd_settime(test->timerfd, 0, &ready, NULL);
+		if (rc < 0) {
+			return PLDM_REQUESTER_POLL_FAIL;
+		}
+
+		/* Don't increment test->cursor as recv needs to consume the current test element */
+	} else {
 		return PLDM_REQUESTER_POLL_FAIL;
 	}
 
 	pollfd->fd = test->timerfd;
 	pollfd->events = POLLIN;
 
-	test->cursor++;
-
 	return 0;
 }
 #endif