As iperf is used on both the sides, iperf is sure what to recieve after each packet.
Basically,
Iperf tool checks the sequence number is incrementing in each datagram it is received. If the sequence number is not incrementing by 1
, there is a loss of datagram. If we receive a datagram with sequence number lesser than previous sequence , then iperf received an out of order packet.
You can refer the iperf source code for better understanding.
https://github.com/esnet/iperf/blob/master/src/iperf_udp.c
From iperf source code-
if (pcount >= sp->packet_count + 1) {
/* Forward, but is there a gap in sequence numbers? */
if (pcount > sp->packet_count + 1) {
/* There's a gap so count that as a loss. */
sp->cnt_error += (pcount - 1) - sp->packet_count;
}
/* Update the highest sequence number seen so far. */
sp->packet_count = pcount;
} else {
/*
* Sequence number went backward (or was stationary?!?).
* This counts as an out-of-order packet.
*/
sp->outoforder_packets++;
/*
* If we have lost packets, then the fact that we are now
* seeing an out-of-order packet offsets a prior sequence
* number gap that was counted as a loss. So we can take
* away a loss.
*/
if (sp->cnt_error > 0)
sp->cnt_error--;
/* Log the out-of-order packet */
if (sp->test->debug)
fprintf(stderr, "OUT OF ORDER - incoming packet sequence %" PRIu64 " but expected sequence %d on stream %d", pcount, sp->packet_count, sp->socket);
}