Skip to content

Commit

Permalink
sock/udp: work around gnrc_sock_recv() returning early timeout
Browse files Browse the repository at this point in the history
sock_udp_recv_buf_aux() sometimes will return -ETIMEDOUT before
the given timeout has expired (e.g. 28798µs instead of 160000µs).

This messes with many assumptions and breaks protocols that rely
on the timeout.

Until we have a proper fix, add this workaround.
  • Loading branch information
benpicco committed Nov 14, 2023
1 parent 978176a commit e3d0068
Showing 1 changed file with 30 additions and 1 deletion.
31 changes: 30 additions & 1 deletion sys/net/gnrc/sock/udp/gnrc_sock_udp.c
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,16 @@ static bool _accept_remote(const sock_udp_t *sock, const udp_hdr_t *hdr,
return true;
}

static uint32_t _now_us(void)
{
#ifdef MODULE_ZTIMER_USEC
return ztimer_now(ZTIMER_USEC);
#endif
#ifdef MODULE_ZTIMER_MSEC
return ztimer_now(ZTIMER_MSEC) * US_PER_MS;
#endif
}

ssize_t sock_udp_recv_buf_aux(sock_udp_t *sock, void **data, void **buf_ctx,
uint32_t timeout, sock_udp_ep_t *remote,
sock_udp_aux_rx_t *aux)
Expand Down Expand Up @@ -274,7 +284,26 @@ ssize_t sock_udp_recv_buf_aux(sock_udp_t *sock, void **data, void **buf_ctx,
_aux.rssi = &aux->rssi;
}
#endif
res = gnrc_sock_recv((gnrc_sock_reg_t *)sock, &pkt, timeout, &tmp, &_aux);
unsigned now = _now_us();
while (1) {
res = gnrc_sock_recv((gnrc_sock_reg_t *)sock, &pkt, timeout, &tmp, &_aux);

if (res != -ETIMEDOUT) {
break;
}

/* HACK: gnrc_sock_recv() sometimes returns -ETIMEDOUT too early */
uint32_t time_elapsed = _now_us() - now;
if (time_elapsed < (timeout - timeout/10)) {
DEBUG("gnrc_sock_udp: timeout happened %"PRIu32" µs early\n",
timeout - time_elapsed);
timeout -= time_elapsed;
now = _now_us();
continue;
}
break;
}

if (res < 0) {
return res;
}
Expand Down

0 comments on commit e3d0068

Please sign in to comment.