From 8992dce4da53c3141acf26bfbe1090c8deb640f7 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Sun, 10 Nov 2019 12:45:48 +0100 Subject: [PATCH] gnrc_sock: consider all pktsnip for gnrc_neterr reporting As analyzed in #12678 there are cases where different reports can be generated for the different snips of the packet send via the `sock`. To catch all errors generated by the stack, the sock has to subscribe for all snips of the packet sent. If any of the snips reports an error distinct from `GNRC_NETERR_SUCCESS` or the previous one, we report that status instead of just the first we receive. This way we are ensured to have the first error reported by the stack for the given packet. --- sys/net/gnrc/sock/gnrc_sock.c | 47 +++++++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/sys/net/gnrc/sock/gnrc_sock.c b/sys/net/gnrc/sock/gnrc_sock.c index 6f7bd9a2f2..09a4634e92 100644 --- a/sys/net/gnrc/sock/gnrc_sock.c +++ b/sys/net/gnrc/sock/gnrc_sock.c @@ -120,6 +120,9 @@ ssize_t gnrc_sock_send(gnrc_pktsnip_t *payload, sock_ip_ep_t *local, kernel_pid_t iface = KERNEL_PID_UNDEF; gnrc_nettype_t type; size_t payload_len = gnrc_pkt_len(payload); +#ifdef MODULE_GNRC_NETERR + unsigned status_subs = 0; +#endif if (local->family != remote->family) { gnrc_pktbuf_release(payload); @@ -172,7 +175,14 @@ ssize_t gnrc_sock_send(gnrc_pktsnip_t *payload, sock_ip_ep_t *local, LL_PREPEND(pkt, netif); } #ifdef MODULE_GNRC_NETERR - gnrc_neterr_reg(pkt); /* no error should occur since pkt was created here */ + /* cppcheck-suppress uninitvar + * (reason: pkt is initialized in AF_INET6 case above, otherwise function + * will return early) */ + for (gnrc_pktsnip_t *ptr = pkt; ptr != NULL; ptr = ptr->next) { + /* no error should occur since pkt was created here */ + gnrc_neterr_reg(ptr); + status_subs++; + } #endif if (!gnrc_netapi_dispatch_send(type, GNRC_NETREG_DEMUX_CTX_ALL, pkt)) { /* this should not happen, but just in case */ @@ -180,17 +190,34 @@ ssize_t gnrc_sock_send(gnrc_pktsnip_t *payload, sock_ip_ep_t *local, return -EBADMSG; } #ifdef MODULE_GNRC_NETERR - msg_t err_report; - err_report.type = 0; + uint32_t last_status = GNRC_NETERR_SUCCESS; - while (err_report.type != GNRC_NETERR_MSG_TYPE) { - msg_try_receive(&err_report); - if (err_report.type != GNRC_NETERR_MSG_TYPE) { - msg_try_send(&err_report, sched_active_pid); + while (status_subs--) { + msg_t err_report; + err_report.type = 0; + + while (err_report.type != GNRC_NETERR_MSG_TYPE) { + msg_try_receive(&err_report); + if (err_report.type != GNRC_NETERR_MSG_TYPE) { + msg_try_send(&err_report, sched_active_pid); + } } - } - if (err_report.content.value != GNRC_NETERR_SUCCESS) { - return (int)(-err_report.content.value); + if (err_report.content.value != last_status) { + int res = (int)(-err_report.content.value); + + for (unsigned i = 0; i < status_subs; i++) { + err_report.type = 0; + /* remove remaining status reports from queue */ + while (err_report.type != GNRC_NETERR_MSG_TYPE) { + msg_try_receive(&err_report); + if (err_report.type != GNRC_NETERR_MSG_TYPE) { + msg_try_send(&err_report, sched_active_pid); + } + } + } + return res; + } + last_status = err_report.content.value; } #endif return payload_len;