diff --git a/src/net.c b/src/net.c index a8c327908..8f28c03ad 100644 --- a/src/net.c +++ b/src/net.c @@ -459,6 +459,17 @@ Nrecv(int fd, char *buf, size_t count, int prot, int sock_opt) break; if (sock_opt & MSG_TRUNC) { + /* + * On a datagram socket MSG_TRUNC returns the full datagram length + * even though only `count` bytes were copied. That length is the + * value the caller must account (fastpath fix: upstream returned + * `count`, so UDP --skip-rx-copy under-reported throughput ~100x). + */ + if (prot == SOCK_DGRAM) { /* Pudp; iperf_api.h is not included here */ + if (r < count) + return NET_HARDERROR; /* at least the UDP message header must be present */ + return r; + } size_t bytes_copied = (r > nleft)? nleft: r; nleft -= bytes_copied; buf += bytes_copied; @@ -538,6 +549,17 @@ Nrecv_no_select(int fd, char *buf, size_t count, int prot, int sock_opt) break; if (sock_opt & MSG_TRUNC) { + /* + * On a datagram socket MSG_TRUNC returns the full datagram length + * even though only `count` bytes were copied. That length is the + * value the caller must account (fastpath fix: upstream returned + * `count`, so UDP --skip-rx-copy under-reported throughput ~100x). + */ + if (prot == SOCK_DGRAM) { /* Pudp; iperf_api.h is not included here */ + if (r < count) + return NET_HARDERROR; /* at least the UDP message header must be present */ + return r; + } size_t bytes_copied = (r > nleft)? nleft: r; nleft -= bytes_copied; buf += bytes_copied;