]> xenbits.xensource.com Git - unikraft/libs/lwip.git/commitdiff
uknetdev: Yield receive thread on full stack queue
authorSimon Kuenzer <simon.kuenzer@neclab.eu>
Thu, 13 Feb 2020 22:50:54 +0000 (23:50 +0100)
committerSimon Kuenzer <simon.kuenzer@neclab.eu>
Fri, 14 Feb 2020 09:14:17 +0000 (10:14 +0100)
When a too high rate of network traffic is received, the netdev's receive
thread may never yield and only forwards packets to the lwip stack
thread. This works as expected until the input queue runs full. If the
the stack is never able to process them, the stack becomes completely
unresponsive. Instead of dropping just a few packets all successive
packets are dropped.

This commit introduces a thread yield when this condition is met and
gives the chance to process queued packets.

Signed-off-by: Simon Kuenzer <simon.kuenzer@neclab.eu>
Reviewed-by: Felipe Huici <felipe.huici@neclab.eu>
uknetdev.c

index 47d2fb19d7133b3e565735e49ff2019b13df8998..704735248be8d05edd40950fe2f160326842266d 100644 (file)
@@ -193,6 +193,7 @@ static void uknetdev_input(struct uk_netdev *dev,
        struct netif *nf = (struct netif *) argp;
        struct uk_netbuf *nb;
        struct pbuf *p;
+       err_t err;
        int ret;
 
        UK_ASSERT(dev);
@@ -243,12 +244,32 @@ static void uknetdev_input(struct uk_netdev *dev,
                p = lwip_netbuf_to_pbuf(nb);
                p->payload = nb->data;
                p->tot_len = p->len = nb->len;
-               if (unlikely(nf->input(p, nf) != ERR_OK)) {
+               err = nf->input(p, nf);
+               if (unlikely(err != ERR_OK)) {
+#if CONFIG_LWIP_THREADS && CONFIG_LIBUKNETDEV_DISPATCHERTHREADS
+                       /* At this point it is possible that lwIP's input queue
+                        * is full or we run out of memory. In this case, we
+                        * return to the scheduler and hope that lwIP's main
+                        * thread is able to process some packets.
+                        * Afterwards, we try it once again.
+                        */
+                       if (err == ERR_MEM) {
+                               LWIP_DEBUGF(NETIF_DEBUG,
+                                           ("%s: %c%c%u: lwIP's input queue full: yielding and trying once again...\n",
+                                            __func__, nf->name[0], nf->name[1],
+                                            nf->num));
+                               uk_sched_yield();
+                               err = nf->input(p, nf);
+                               if (likely(err == ERR_OK))
+                                       continue;
+                       }
+#endif
+
                        /*
                         * Drop the packet that we could not send to the stack
                         */
-                       uk_pr_err("%c%c%u: Failed to forward packet to lwIP\n",
-                                 nf->name[0], nf->name[1], nf->num);
+                       uk_pr_err("%c%c%u: Failed to forward packet to lwIP: %d\n",
+                                 nf->name[0], nf->name[1], nf->num, err);
                        uk_netbuf_free_single(nb);
                }
        } while (uk_netdev_status_more(ret));