--- a/sys/dev/virtual/vmware/vmxnet3/if_vmx.c +++ b/sys/dev/virtual/vmware/vmxnet3/if_vmx.c @@ -2195,6 +2195,9 @@ vmxnet3_rxq_eof(struct vmxnet3_rxqueue *r struct vmxnet3_rxcompdesc *rxcd; struct mbuf *m, *m_head, *m_tail; int idx, length; + int budget = vmxnet3_rx_budget; sc = rxq->vxrxq_sc; ifp = sc->vmx_ifp; @@ -2201,6 +2204,17 @@ vmxnet3_rxq_eof(struct vmxnet3_rxqueue *r for (;;) { + /* + * DF-3782: bound the completion walk so a host that + * (nominally on behalf of a line-rate remote flood) + * keeps the ring populated cannot livelock the + * interrupt thread holding the RXQ lock. + */ + if (--budget <= 0) { + rxq->vxrxq_mhead = m_head; + rxq->vxrxq_mtail = m_tail; + rxq->vxrxq_more = 1; + break; + } rxcd = &rxc->vxcr_u.rxcd[rxc->vxcr_next]; if (rxcd->gen != rxc->vxcr_gen) { rxq->vxrxq_mhead = m_head; *** NOTE 1: adds `int vmxnet3_rx_budget = 256;` (+TUNABLE_INT *** "hw.vmx.rx_budget") and a `vxrxq_more` flag to struct vmxnet3_rxqueue *** (if_vmxvar.h); the interrupt handlers must, when vxrxq_more is set, *** re-arm via callout_reset(&rxq->vxrxq_callout, 1, ...) instead of *** returning to idle, so already-deposited completions are not stranded. *** NOTE 2: advisory diff — not validated on hardware (no vmxnet3 device *** on the audit guest).