summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorafedorov <afedorov@ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f>2020-12-17 16:52:40 +0000
committerafedorov <afedorov@ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f>2020-12-17 16:52:40 +0000
commit1703e5eadaf2ed9906fdcd6092b745e54306d9fc (patch)
tree7237a57d178eecced4f80999f498af9b0e8b2ceb
parentb6f0b18537a3f926dd47c04c89b6779611f2affe (diff)
downloadfreebsd-1703e5eadaf2ed9906fdcd6092b745e54306d9fc.tar.gz
freebsd-1703e5eadaf2ed9906fdcd6092b745e54306d9fc.tar.bz2
[bhyve] virtio-net: Do not allow receiving packets until features have been negotiated.
Enforce the requirement that the RX callback cannot be called after a reset until the features have been negotiated. This fixes a race condition where the receive callback is called during a device reset. Reviewed by: vmaffione, grehan Approved by: vmaffione (mentor) Sponsored by: vstack.com Differential Revision: https://reviews.freebsd.org/D27381 git-svn-id: http://svn.freebsd.org/base/head@368720 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f
-rw-r--r--usr.sbin/bhyve/pci_virtio_net.c19
1 files changed, 19 insertions, 0 deletions
diff --git a/usr.sbin/bhyve/pci_virtio_net.c b/usr.sbin/bhyve/pci_virtio_net.c
index 346c4238151..ac728b611c4 100644
--- a/usr.sbin/bhyve/pci_virtio_net.c
+++ b/usr.sbin/bhyve/pci_virtio_net.c
@@ -111,6 +111,8 @@ struct pci_vtnet_softc {
net_backend_t *vsc_be;
+ bool features_negotiated; /* protected by rx_mtx */
+
int resetting; /* protected by tx_mtx */
uint64_t vsc_features; /* negotiated features */
@@ -176,6 +178,7 @@ pci_vtnet_reset(void *vsc)
* Receive operation will be enabled again once the guest adds
* the first receive buffers and kicks us.
*/
+ sc->features_negotiated = false;
netbe_rx_disable(sc->vsc_be);
/* Set sc->resetting and give a chance to the TX thread to stop. */
@@ -246,6 +249,12 @@ pci_vtnet_rx(struct pci_vtnet_softc *sc)
struct vqueue_info *vq;
vq = &sc->vsc_queues[VTNET_RXQ];
+
+ /* Features must be negotiated */
+ if (!sc->features_negotiated) {
+ return;
+ }
+
for (;;) {
struct virtio_net_rxhdr *hdr;
uint32_t riov_bytes;
@@ -406,8 +415,14 @@ pci_vtnet_ping_rxq(void *vsc, struct vqueue_info *vq)
/*
* A qnotify means that the rx process can now begin.
+ * Enable RX only if features are negotiated.
*/
pthread_mutex_lock(&sc->rx_mtx);
+ if (!sc->features_negotiated) {
+ pthread_mutex_unlock(&sc->rx_mtx);
+ return;
+ }
+
vq_kick_disable(vq);
netbe_rx_enable(sc->vsc_be);
pthread_mutex_unlock(&sc->rx_mtx);
@@ -750,6 +765,10 @@ pci_vtnet_neg_features(void *vsc, uint64_t negotiated_features)
netbe_set_cap(sc->vsc_be, negotiated_features, sc->vhdrlen);
sc->be_vhdrlen = netbe_get_vnet_hdr_len(sc->vsc_be);
assert(sc->be_vhdrlen == 0 || sc->be_vhdrlen == sc->vhdrlen);
+
+ pthread_mutex_lock(&sc->rx_mtx);
+ sc->features_negotiated = true;
+ pthread_mutex_unlock(&sc->rx_mtx);
}
#ifdef BHYVE_SNAPSHOT