diff options
author | Vincenzo Maffione <vmaffione@FreeBSD.org> | 2020-06-03 17:46:21 +0000 |
---|---|---|
committer | Vincenzo Maffione <vmaffione@FreeBSD.org> | 2020-06-03 17:46:21 +0000 |
commit | 1b6d5a80a66006100d03f67d259777ae01bea23d (patch) | |
tree | 6845ea3094ea6c2e6f985e5589a4bd692483ba11 | |
parent | 2d769e25b1d525edcf747c2058ce2b7c9e6c6699 (diff) |
Notes
-rw-r--r-- | sys/dev/netmap/if_vtnet_netmap.h | 21 |
1 files changed, 18 insertions, 3 deletions
diff --git a/sys/dev/netmap/if_vtnet_netmap.h b/sys/dev/netmap/if_vtnet_netmap.h index c34798a3c176..157cea56218e 100644 --- a/sys/dev/netmap/if_vtnet_netmap.h +++ b/sys/dev/netmap/if_vtnet_netmap.h @@ -310,8 +310,11 @@ vtnet_netmap_rxsync(struct netmap_kring *kring, int flags) /* * First part: import newly received packets. * Only accept our own buffers (matching the token). We should only get - * matching buffers. We may need to stop early to avoid hwtail to overrun - * hwcur. + * matching buffers. The hwtail should never overrun hwcur, because + * we publish only N-1 receive buffers (and non N). + * In any case we must not leave this routine with the interrupts + * disabled, pending packets in the VQ and hwtail == (hwcur - 1), + * otherwise the pending packets could stall. */ if (netmap_no_pendintr || force_update) { uint32_t hwtail_lim = nm_prev(kring->nr_hwcur, lim); @@ -320,10 +323,17 @@ vtnet_netmap_rxsync(struct netmap_kring *kring, int flags) vtnet_rxq_disable_intr(rxq); nm_i = kring->nr_hwtail; - while (nm_i != hwtail_lim) { + for (;;) { int len; token = virtqueue_dequeue(vq, &len); if (token == NULL) { + /* + * Enable the interrupts again and double-check + * for more work. We can go on until we win the + * race condition, since we are not replenishing + * in the meanwhile, and thus we will process at + * most N-1 slots. + */ if (interrupts && vtnet_rxq_enable_intr(rxq)) { vtnet_rxq_disable_intr(rxq); continue; @@ -333,6 +343,11 @@ vtnet_netmap_rxsync(struct netmap_kring *kring, int flags) if (unlikely(token != (void *)rxq)) { nm_prerr("BUG: RX token mismatch"); } else { + if (nm_i == hwtail_lim) { + KASSERT(false, ("hwtail would " + "overrun hwcur")); + } + /* Skip the virtio-net header. */ len -= sc->vtnet_hdr_size; if (unlikely(len < 0)) { |