From fe132cb6d4f7472ab02941cd7c1620de69672865 Mon Sep 17 00:00:00 2001 From: Simon Kuenzer Date: Tue, 12 Oct 2021 17:19:03 +0200 Subject: [PATCH 1/9] Probe network device features Latest lib/uknetdev updates make it necessary that new network interfaces need to be probed for feature negotiation before the interface can be used. Signed-off-by: Simon Kuenzer --- init.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/init.c b/init.c index 5502bd3..584c0a5 100644 --- a/init.c +++ b/init.c @@ -138,6 +138,7 @@ static int liblwip_init(void) const char __maybe_unused *strcfg; uint16_t __maybe_unused int16cfg; int is_first_nf; + int ret; #if LWIP_IPV4 ip4_addr_t ip4; ip4_addr_t *ip4_arg; @@ -174,12 +175,25 @@ static int liblwip_init(void) dev = uk_netdev_get(devid); if (!dev) continue; - if (uk_netdev_state_get(dev) != UK_NETDEV_UNCONFIGURED) { + if (uk_netdev_state_get(dev) != UK_NETDEV_UNCONFIGURED + && uk_netdev_state_get(dev) != UK_NETDEV_UNPROBED) { uk_pr_info("Skipping to add network device %u to lwIP: Not in unconfigured state\n", devid); continue; } + if (uk_netdev_state_get(dev) == UK_NETDEV_UNPROBED) { + ret = uk_netdev_probe(dev); + if (ret < 0) { + uk_pr_err("Failed to probe features of network device %u: %d; skipping device...\n", + devid, ret); + continue; + } + } + + /* Here, the device has to be in unconfigured state */ + UK_ASSERT(uk_netdev_state_get(dev) == UK_NETDEV_UNCONFIGURED); + uk_pr_info("Attach network device %u to lwIP...\n", devid); From abcb328b2d1068ec45452bf86be3ff3777416efb Mon Sep 17 00:00:00 2001 From: Simon Kuenzer Date: Tue, 12 Oct 2021 17:22:01 +0200 Subject: [PATCH 2/9] Print network device hardware address During network device initialization, print the hardware address of the network device to the info kernel console. This should simplify first-level of diagnosis. Signed-off-by: Simon Kuenzer --- init.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/init.c b/init.c index 584c0a5..3e054d4 100644 --- a/init.c +++ b/init.c @@ -253,6 +253,14 @@ static int liblwip_init(void) continue; } + /* Print hardware address */ + if (nf->hwaddr_len == 6) { + uk_pr_info("%c%c%u: Hardware address: %02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8"\n", + nf->name[0], nf->name[1], nf->num, + nf->hwaddr[0], nf->hwaddr[1], nf->hwaddr[2], + nf->hwaddr[3], nf->hwaddr[4], nf->hwaddr[5]); + } + /* Declare the first network device as default interface */ if (is_first_nf) { uk_pr_info("%c%c%u: Set as default interface\n", From 87233136f7416490c87001ddc8fc4768a270ca83 Mon Sep 17 00:00:00 2001 From: Simon Kuenzer Date: Tue, 12 Oct 2021 17:24:04 +0200 Subject: [PATCH 3/9] Print per-device checksum configuration During network device initialization, print the checksum handling configuration that get set by the underlying uknetdev driver. This should simplify first-level of diagnosis. Signed-off-by: Simon Kuenzer --- init.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/init.c b/init.c index 3e054d4..c729eb3 100644 --- a/init.c +++ b/init.c @@ -261,6 +261,46 @@ static int liblwip_init(void) nf->hwaddr[3], nf->hwaddr[4], nf->hwaddr[5]); } +#if LWIP_CHECKSUM_CTRL_PER_NETIF + uk_pr_info("%c%c%u: Check checksums:", + nf->name[0], nf->name[1], nf->num); + IF__NETIF_CHECKSUM_ENABLED(nf, NETIF_CHECKSUM_CHECK_IP) { + uk_pr_info(" IP"); + } + IF__NETIF_CHECKSUM_ENABLED(nf, NETIF_CHECKSUM_CHECK_UDP) { + uk_pr_info(" UDP"); + } + IF__NETIF_CHECKSUM_ENABLED(nf, NETIF_CHECKSUM_CHECK_TCP) { + uk_pr_info(" TCP"); + } + IF__NETIF_CHECKSUM_ENABLED(nf, NETIF_CHECKSUM_CHECK_ICMP) { + uk_pr_info(" ICMP"); + } + IF__NETIF_CHECKSUM_ENABLED(nf, NETIF_CHECKSUM_CHECK_ICMP6) { + uk_pr_info(" ICMP6"); + } + uk_pr_info("\n"); + + uk_pr_info("%c%c%u: Generate checksums:", + nf->name[0], nf->name[1], nf->num); + IF__NETIF_CHECKSUM_ENABLED(nf, NETIF_CHECKSUM_GEN_IP) { + uk_pr_info(" IP"); + } + IF__NETIF_CHECKSUM_ENABLED(nf, NETIF_CHECKSUM_GEN_UDP) { + uk_pr_info(" UDP"); + } + IF__NETIF_CHECKSUM_ENABLED(nf, NETIF_CHECKSUM_GEN_TCP) { + uk_pr_info(" TCP"); + } + IF__NETIF_CHECKSUM_ENABLED(nf, NETIF_CHECKSUM_GEN_ICMP) { + uk_pr_info(" ICMP"); + } + IF__NETIF_CHECKSUM_ENABLED(nf, NETIF_CHECKSUM_GEN_ICMP6) { + uk_pr_info(" ICMP6"); + } + uk_pr_info("\n"); +#endif /* LWIP_CHECKSUM_CTRL_PER_NETIF */ + /* Declare the first network device as default interface */ if (is_first_nf) { uk_pr_info("%c%c%u: Set as default interface\n", From f9e7d1426b786217946033625078c73f2dfa8e2a Mon Sep 17 00:00:00 2001 From: Simon Kuenzer Date: Tue, 9 Nov 2021 17:40:48 +0100 Subject: [PATCH 4/9] uknetdev: Adopt to refactored uknetdev feature macros The netdev device features were refactored in `lib/uknetdev`. This commit adopts the usage for initializing interrupt and polling mode for a device: `UK_FEATURE_RXQ_INTR_AVAILABLE` is now called `UK_NETDEV_F_RXQ_INTR`. Signed-off-by: Simon Kuenzer --- uknetdev.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/uknetdev.c b/uknetdev.c index 091370a..0e28717 100644 --- a/uknetdev.c +++ b/uknetdev.c @@ -349,7 +349,6 @@ static void uknetdev_updown(struct netif *nf) lwip_data = (struct lwip_netdev_data *)dev->scratch_pad; /* Enable and disable interrupts according to netif's up/down status */ - if (nf->flags & NETIF_FLAG_UP) { if (uk_netdev_rxintr_supported(lwip_data->dev_info.features)) { ret = uk_netdev_rxq_intr_enable(dev, 0); @@ -477,7 +476,7 @@ err_t uknetdev_init(struct netif *nf) return ERR_IF; #if CONFIG_LWIP_UKNETDEV_POLLONLY /* Unset receive interrupt support: We force polling mode */ - lwip_data->dev_info.features &= ~UK_FEATURE_RXQ_INTR_AVAILABLE; + lwip_data->dev_info.features &= ~UK_NETDEV_F_RXQ_INTR; #endif /* CONFIG_LWIP_UKNETDEV_POLLONLY */ lwip_data->pkt_a = a; From c4814cb065fe53beef57ea239ad8cbb6f307b10b Mon Sep 17 00:00:00 2001 From: Simon Kuenzer Date: Fri, 20 Aug 2021 18:39:10 +0200 Subject: [PATCH 5/9] uknetdev: Always check checksum of IP header Like Linux, we enable checking the checksum of the IP header on packet reception and let lwIP drop the packet if it was invalid. Signed-off-by: Simon Kuenzer --- uknetdev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/uknetdev.c b/uknetdev.c index 0e28717..d59a99a 100644 --- a/uknetdev.c +++ b/uknetdev.c @@ -595,7 +595,8 @@ err_t uknetdev_init(struct netif *nf) | NETIF_CHECKSUM_GEN_UDP | NETIF_CHECKSUM_GEN_TCP | NETIF_CHECKSUM_GEN_ICMP - | NETIF_CHECKSUM_GEN_ICMP6)); + | NETIF_CHECKSUM_GEN_ICMP6 + | NETIF_CHECKSUM_CHECK_IP)); LWIP_DEBUGF(NETIF_DEBUG, ("%s: %c%c%u: chksum_flags: %"PRIx16"\n", __func__, nf->name[0], nf->name[1], nf->num, From 76a2e840b511015d9918158cce263e876a040ea3 Mon Sep 17 00:00:00 2001 From: Simon Kuenzer Date: Fri, 20 Aug 2021 18:39:52 +0200 Subject: [PATCH 6/9] uknetdev: Update comment regarding async zero-copy TX Add more details why we need to copy a packet for transmission. We support asynchronous transmit but not with zero-copy. Problem is that lwIP may modify a packet header for preparing retransmissions while the NIC is still accessing the packet buffer for transmission. Signed-off-by: Simon Kuenzer --- uknetdev.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/uknetdev.c b/uknetdev.c index d59a99a..7d58800 100644 --- a/uknetdev.c +++ b/uknetdev.c @@ -163,8 +163,12 @@ static err_t uknetdev_output(struct netif *nf, struct pbuf *p) /* * Copy pbuf to netbuf - * NOTE: Unfortunately, lwIP seems not to support zero-copy transmit, - * yet. As long as we do not have this, we have to copy. + * NOTE: Unfortunately, lwIP seems not to support asynchronous zero-copy + * transmit, yet. As long as we do not have this, we have to copy + * for being still able to asynchronously transmit. At least this + * needs to be done for TCP traffic because of potential + * retransmissions. + * Further information: https://savannah.nongnu.org/task/?7896 */ wpos = nb->data; for (q = p; q != NULL; q = q->next) { From 0a602a32427f33c8b6fed96f52c776edd0f827f3 Mon Sep 17 00:00:00 2001 From: Simon Kuenzer Date: Fri, 20 Aug 2021 18:42:13 +0200 Subject: [PATCH 7/9] uknetdev: Enable support for hardware checksum offloading This commit implements and enables checksum offloading with the Unikraft fork of lwIP and if the underlying uknetdev device announced support for it. For non-supported devices, all checksums are checked and computed. When an lwIP stack version is used that currently does not support checksum offloading, the original behavior is kept. Signed-off-by: Simon Kuenzer --- Config.uk | 1 + include/lwipopts.h | 13 +++++ uknetdev.c | 137 ++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 136 insertions(+), 15 deletions(-) diff --git a/Config.uk b/Config.uk index be7e74c..1711845 100644 --- a/Config.uk +++ b/Config.uk @@ -42,6 +42,7 @@ config LWIP_UNIKRAFT21X recent bugfixes and security patches, and includes latest features developed by the Unikraft community that are currently upstreamed to lwIP. + This version supports checksum offloading. endchoice menu "Netif drivers" diff --git a/include/lwipopts.h b/include/lwipopts.h index 4433bed..72f52da 100644 --- a/include/lwipopts.h +++ b/include/lwipopts.h @@ -328,6 +328,19 @@ void sys_free(void *ptr); #define CHECKSUM_CHECK_ICMP6 1 #define CHECKSUM_CHECK_TCP 1 +/* + * As long as partial checksummin gis not upstream available, + * enable it only when Unirkaft's fork of lwIP is selected. + */ +#if CONFIG_LWIP_UNIKRAFT21X +#define LWIP_CHECKSUM_PARTIAL 1 + +#define CHECKSUM_PARTIAL_UDP 1 +#define CHECKSUM_PARTIAL_TCP 1 +#define CHECKSUM_SKIPVALID_UDP 1 +#define CHECKSUM_SKIPVALID_TCP 1 +#endif /* CONFIG_LWIP_UNIKRAFT21X */ + /** * Debugging options */ diff --git a/uknetdev.c b/uknetdev.c index 7d58800..3ede770 100644 --- a/uknetdev.c +++ b/uknetdev.c @@ -170,12 +170,47 @@ static err_t uknetdev_output(struct netif *nf, struct pbuf *p) * retransmissions. * Further information: https://savannah.nongnu.org/task/?7896 */ + LWIP_DEBUGF(NETIF_DEBUG, + ("%s: %c%c%u: Prepare netbuf for %"PRIu16" bytes (headroom: %"__PRIsz"):", + __func__, nf->name[0], nf->name[1], nf->num, p->tot_len, uk_netbuf_headroom(nb))); wpos = nb->data; for (q = p; q != NULL; q = q->next) { memcpy(wpos, q->payload, q->len); + +#if LWIP_CHECKSUM_CTRL_PER_NETIF && LWIP_CHECKSUM_PARTIAL +#if (NETIF_DEBUG == LWIP_DBG_ON) + LWIP_DEBUGF(NETIF_DEBUG, + (" [%"U16_F"B %c%c", + q->len, + q->flags & PBUF_FLAG_CSUM_PARTIAL ? 'C' : '-', + q->flags & PBUF_FLAG_DATA_VALID ? 'V' : '-')); + if (q->flags & PBUF_FLAG_CSUM_PARTIAL) { + LWIP_DEBUGF(NETIF_DEBUG, + (" chksum @ %"S32_F":%"U16_F, + q->csum_start, q->csum_offset)); + } + LWIP_DEBUGF(NETIF_DEBUG, ("]")); +#endif /* (NETIF_DEBUG == LWIP_DBG_ON) */ + /* + * One pbuf of the chain (typically the first one) + * could have the CSUM_PARTIAL flag set + */ + if (q->flags & PBUF_FLAG_CSUM_PARTIAL) { + /* checksum bit can only be set once */ + UK_ASSERT(!(nb->flags & UK_NETBUF_F_PARTIAL_CSUM)); + + nb->flags |= (UK_NETBUF_F_PARTIAL_CSUM); + nb->csum_start = p->csum_start + nb->len; + nb->csum_offset = p->csum_offset; + } + nb->flags |= (q->flags & PBUF_FLAG_DATA_VALID) ? UK_NETBUF_F_DATA_VALID : 0x0; +#endif /* LWIP_CHECKSUM_CTRL_PER_NETIF && LWIP_CHECKSUM_PARTIAL */ + wpos += q->len; + nb->len += q->len; } - nb->len = p->tot_len; + LWIP_DEBUGF(NETIF_DEBUG, ("\n")); + UK_ASSERT(nb->len == p->tot_len); /* Transmit packet */ do { @@ -245,15 +280,48 @@ static void uknetdev_input(struct uk_netdev *dev, break; } + /* Send packet to lwip */ + p = lwip_netbuf_to_pbuf(nb); + p->payload = nb->data; + p->tot_len = p->len = nb->len; +#if LWIP_CHECKSUM_CTRL_PER_NETIF && LWIP_CHECKSUM_PARTIAL + /* NOTE: We need to be careful that we do not erase any existing + * pbuf flags here. The receive queue was filled with + * netbufs allocated by `lwip_alloc_netbuf()`. This + * function sets `PBUF_FLAG_IS_CUSTOM` so that lwIP can + * properly free the encapsulated pbufs. + */ + UK_ASSERT((p->flags & PBUF_FLAG_IS_CUSTOM) != 0); + + p->flags |= (nb->flags & UK_NETBUF_F_PARTIAL_CSUM) + ? PBUF_FLAG_CSUM_PARTIAL : 0; + p->flags |= (nb->flags & UK_NETBUF_F_DATA_VALID) + ? PBUF_FLAG_DATA_VALID : 0; + + p->csum_start = (s32_t) nb->csum_start; + p->csum_offset = nb->csum_offset; + +#if (NETIF_DEBUG == LWIP_DBG_ON) + LWIP_DEBUGF(NETIF_DEBUG, + ("%s: %c%c%u: Received %"PRIu16" bytes: [%uB %c%c", + __func__, nf->name[0], nf->name[1], nf->num, + p->tot_len, p->len, + (p->flags & PBUF_FLAG_CSUM_PARTIAL) ? 'C' : '-', + (p->flags & PBUF_FLAG_DATA_VALID) ? 'V' : '-')); + if (p->flags & PBUF_FLAG_CSUM_PARTIAL) { + LWIP_DEBUGF(NETIF_DEBUG, + (" chksum @ %"S32_F":%"U16_F, + p->csum_start, p->csum_offset)); + } + LWIP_DEBUGF(NETIF_DEBUG, ("]\n")); +#endif /* (NETIF_DEBUG == LWIP_DBG_ON) */ +#else /* !(LWIP_CHECKSUM_CTRL_PER_NETIF && LWIP_CHECKSUM_PARTIAL) */ LWIP_DEBUGF(NETIF_DEBUG, ("%s: %c%c%u: Received %"PRIu16" bytes\n", __func__, nf->name[0], nf->name[1], nf->num, nb->len)); +#endif /* !(LWIP_CHECKSUM_CTRL_PER_NETIF && LWIP_CHECKSUM_PARTIAL) */ - /* Send packet to lwip */ - p = lwip_netbuf_to_pbuf(nb); - p->payload = nb->data; - p->tot_len = p->len = nb->len; err = nf->input(p, nf); if (unlikely(err != ERR_OK)) { #if CONFIG_LWIP_THREADS && CONFIG_LIBUKNETDEV_DISPATCHERTHREADS @@ -582,18 +650,56 @@ err_t uknetdev_init(struct netif *nf) __func__, nf->name[0], nf->name[1], nf->num, nf->flags)); #if LWIP_CHECKSUM_CTRL_PER_NETIF +#if LWIP_CHECKSUM_PARTIAL + if (uk_netdev_partial_csum_supported(lwip_data->dev_info.features)) { + /* + * Do partial checksumming for UDP and TCP + */ + NETIF_SET_CHECKSUM_CTRL(nf, (NETIF_CHECKSUM_GEN_IP + | NETIF_CHECKSUM_CHECK_IP + | NETIF_CHECKSUM_GEN_UDP + | NETIF_CHECKSUM_PARTIAL_UDP + | NETIF_CHECKSUM_CHECK_UDP + | NETIF_CHECKSUM_SKIPVALID_UDP + | NETIF_CHECKSUM_GEN_TCP + | NETIF_CHECKSUM_PARTIAL_TCP + | NETIF_CHECKSUM_CHECK_TCP + | NETIF_CHECKSUM_SKIPVALID_TCP + | NETIF_CHECKSUM_GEN_ICMP + | NETIF_CHECKSUM_CHECK_ICMP + | NETIF_CHECKSUM_GEN_ICMP6 + | NETIF_CHECKSUM_CHECK_ICMP6)); + } else { + /* + * Do complete checksumming of outgoing packets + * and check everything incoming + */ + NETIF_SET_CHECKSUM_CTRL(nf, (NETIF_CHECKSUM_GEN_IP + | NETIF_CHECKSUM_GEN_UDP + | NETIF_CHECKSUM_GEN_TCP + | NETIF_CHECKSUM_GEN_ICMP + | NETIF_CHECKSUM_GEN_ICMP6 + | NETIF_CHECKSUM_CHECK_IP + | NETIF_CHECKSUM_CHECK_UDP + | NETIF_CHECKSUM_CHECK_TCP + | NETIF_CHECKSUM_CHECK_ICMP + | NETIF_CHECKSUM_CHECK_ICMP6)); + } +#else /* !LWIP_CHECKSUM_PARTIAL */ /* * Checksum settings - * TODO: libuknetdev does not support checksum capabilities yet. - * Because of this, we need to calculate the checksum for every - * outgoing packet in software. We assume that we receive packets - * from a virtual interface, so the host was doing a check for us - * already. In case of guest-to-guest communication, the checksum - * field may be incorrect because the other guest expects that the - * host is offloading the calculation to hardware as soon as a - * packet leaves the physical host machine. At this point, the - * best we can do is not to check any checksums on incoming - * traffic and assume everything is fine. + * NOTE: We assume that we receive packets from a virtual interface, + * the host should have done a check for us already. We will not + * check checksum on incoming packets. The reason is that in + * case of guest-to-guest communication, the checksum field may be + * different compared when received from a physical network. The + * reason is that in virtual environments typically the host is + * offloading the calculation to hardware as soon as a + * packet leaves the physical host machine, otherwise the field + * stays untouched (e.g., guest-to-guest communication). At this + * point, the best we can do with lwIP is not to check any + * checksums on incoming traffic and compute one for outgoing + * traffic. */ NETIF_SET_CHECKSUM_CTRL(nf, (NETIF_CHECKSUM_GEN_IP | NETIF_CHECKSUM_GEN_UDP @@ -601,6 +707,7 @@ err_t uknetdev_init(struct netif *nf) | NETIF_CHECKSUM_GEN_ICMP | NETIF_CHECKSUM_GEN_ICMP6 | NETIF_CHECKSUM_CHECK_IP)); +#endif /* !LWIP_CHECKSUM_PARTIAL */ LWIP_DEBUGF(NETIF_DEBUG, ("%s: %c%c%u: chksum_flags: %"PRIx16"\n", __func__, nf->name[0], nf->name[1], nf->num, From 90fdbc8233ca8d2214967c8745c82ae1d28d5c8a Mon Sep 17 00:00:00 2001 From: Simon Kuenzer Date: Tue, 9 Nov 2021 17:36:12 +0100 Subject: [PATCH 8/9] init: Indicate hardware checksum offloading features During netif initialization, the handling of checksums is printed per device with the info level. This commits adds the following properties next to the protocols: - For received traffic - `[+partial]` Driver and device additionally support receiving of partial checksummed packets. - `[+offloaded]` Driver and device additionally skip checksum validation of already validated packets, e.g., by a physical NIC on the host. - For transmitted traffic - `[partial]` Generated packets will only have a partial checksum computed in software. The rest of the checksum is intended to be computed by a physical NIC on the host. Signed-off-by: Simon Kuenzer --- init.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/init.c b/init.c index c729eb3..ed439d2 100644 --- a/init.c +++ b/init.c @@ -269,9 +269,25 @@ static int liblwip_init(void) } IF__NETIF_CHECKSUM_ENABLED(nf, NETIF_CHECKSUM_CHECK_UDP) { uk_pr_info(" UDP"); +#if LWIP_CHECKSUM_PARTIAL + IF__NETIF_CHECKSUM_ENABLED(nf, NETIF_CHECKSUM_PARTIAL_UDP) { + uk_pr_info("[+partial]"); + } + IF__NETIF_CHECKSUM_ENABLED(nf, NETIF_CHECKSUM_SKIPVALID_UDP) { + uk_pr_info("[+offloaded]"); + } +#endif /* LWIP_CHECKSUM_PARTIAL */ } IF__NETIF_CHECKSUM_ENABLED(nf, NETIF_CHECKSUM_CHECK_TCP) { uk_pr_info(" TCP"); +#if LWIP_CHECKSUM_PARTIAL + IF__NETIF_CHECKSUM_ENABLED(nf, NETIF_CHECKSUM_PARTIAL_TCP) { + uk_pr_info("[+partial]"); + } + IF__NETIF_CHECKSUM_ENABLED(nf, NETIF_CHECKSUM_SKIPVALID_TCP) { + uk_pr_info("[+offloaded]"); + } +#endif /* LWIP_CHECKSUM_PARTIAL */ } IF__NETIF_CHECKSUM_ENABLED(nf, NETIF_CHECKSUM_CHECK_ICMP) { uk_pr_info(" ICMP"); @@ -288,9 +304,19 @@ static int liblwip_init(void) } IF__NETIF_CHECKSUM_ENABLED(nf, NETIF_CHECKSUM_GEN_UDP) { uk_pr_info(" UDP"); +#if LWIP_CHECKSUM_PARTIAL + IF__NETIF_CHECKSUM_ENABLED(nf, NETIF_CHECKSUM_PARTIAL_UDP) { + uk_pr_info("[partial]"); + } +#endif /* LWIP_CHECKSUM_PARTIAL */ } IF__NETIF_CHECKSUM_ENABLED(nf, NETIF_CHECKSUM_GEN_TCP) { uk_pr_info(" TCP"); +#if LWIP_CHECKSUM_PARTIAL + IF__NETIF_CHECKSUM_ENABLED(nf, NETIF_CHECKSUM_PARTIAL_TCP) { + uk_pr_info("[partial]"); + } +#endif /* LWIP_CHECKSUM_PARTIAL */ } IF__NETIF_CHECKSUM_ENABLED(nf, NETIF_CHECKSUM_GEN_ICMP) { uk_pr_info(" ICMP"); From 7d33417ccd24f5d96ff30eab3bb8c2e6ce9836eb Mon Sep 17 00:00:00 2001 From: Simon Kuenzer Date: Tue, 9 Nov 2021 17:40:02 +0100 Subject: [PATCH 9/9] uknetdev: Yield on busy-waiting for transmit Whenever we need to wait for the device/driver to be ready for sending out another packet, we enter a busy-wait loop. With this commit, we call `uk_sched_yield()` while we wait so that other threads in the system can be executed. Signed-off-by: Simon Kuenzer --- uknetdev.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/uknetdev.c b/uknetdev.c index 3ede770..f70c6d1 100644 --- a/uknetdev.c +++ b/uknetdev.c @@ -213,9 +213,12 @@ static err_t uknetdev_output(struct netif *nf, struct pbuf *p) UK_ASSERT(nb->len == p->tot_len); /* Transmit packet */ - do { + ret = uk_netdev_tx_one(dev, 0, nb); + while (unlikely(uk_netdev_status_notready(ret))) { + /* Allow other threads to do work and re-try */ + uk_sched_yield(); ret = uk_netdev_tx_one(dev, 0, nb); - } while (uk_netdev_status_notready(ret)); + } if (unlikely(ret < 0)) { LWIP_DEBUGF(NETIF_DEBUG, ("%s: %c%c%u: Failed to send %"PRIu16" bytes\n",