Author: grehan
Date: Tue Sep 16 19:08:54 2014
New Revision: 271685
URL: http://svnweb.freebsd.org/changeset/base/271685

Log:
  MFC virtio-net changes.
  
  Re-tested with NetBSD/amd64 5.2.2, 6.1.4 and 7-beta.
  
  r271299:
  Add a callback to be notified about negotiated features.
  
  r271338:
  Allow vtnet operation without merged rx buffers.
  
  NetBSD's virtio-net implementation doesn't negotiate
  the merged rx-buffers feature. To support this, check
  to see if the feature was negotiated, and then adjust
  the operation of the receive path accordingly by using
  a larger iovec, and a smaller rx header.
  In addition, ignore writes to the (read-only) status byte.
  
  Approved by:  re (glebius)
  Obtained from:        Vincenzo Maffione, Universita` di Pisa (r271299)

Modified:
  stable/10/usr.sbin/bhyve/pci_virtio_block.c
  stable/10/usr.sbin/bhyve/pci_virtio_net.c
  stable/10/usr.sbin/bhyve/pci_virtio_rnd.c
  stable/10/usr.sbin/bhyve/virtio.c
  stable/10/usr.sbin/bhyve/virtio.h
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/usr.sbin/bhyve/pci_virtio_block.c
==============================================================================
--- stable/10/usr.sbin/bhyve/pci_virtio_block.c Tue Sep 16 18:02:24 2014        
(r271684)
+++ stable/10/usr.sbin/bhyve/pci_virtio_block.c Tue Sep 16 19:08:54 2014        
(r271685)
@@ -133,6 +133,7 @@ static struct virtio_consts vtblk_vi_con
        pci_vtblk_notify,       /* device-wide qnotify */
        pci_vtblk_cfgread,      /* read PCI config */
        pci_vtblk_cfgwrite,     /* write PCI config */
+       NULL,                   /* apply negotiated features */
        VTBLK_S_HOSTCAPS,       /* our capabilities */
 };
 

Modified: stable/10/usr.sbin/bhyve/pci_virtio_net.c
==============================================================================
--- stable/10/usr.sbin/bhyve/pci_virtio_net.c   Tue Sep 16 18:02:24 2014        
(r271684)
+++ stable/10/usr.sbin/bhyve/pci_virtio_net.c   Tue Sep 16 19:08:54 2014        
(r271685)
@@ -135,11 +135,14 @@ struct pci_vtnet_softc {
        int             vsc_rx_ready;
        volatile int    resetting;      /* set and checked outside lock */
 
-       uint32_t        vsc_features;
+       uint64_t        vsc_features;   /* negotiated features */
+       
        struct virtio_net_config vsc_config;
 
        pthread_mutex_t rx_mtx;
        int             rx_in_progress;
+       int             rx_vhdrlen;
+       int             rx_merge;       /* merged rx bufs in use */
 
        pthread_t       tx_tid;
        pthread_mutex_t tx_mtx;
@@ -151,6 +154,7 @@ static void pci_vtnet_reset(void *);
 /* static void pci_vtnet_notify(void *, struct vqueue_info *); */
 static int pci_vtnet_cfgread(void *, int, int, uint32_t *);
 static int pci_vtnet_cfgwrite(void *, int, int, uint32_t);
+static void pci_vtnet_neg_features(void *, uint64_t);
 
 static struct virtio_consts vtnet_vi_consts = {
        "vtnet",                /* our name */
@@ -160,6 +164,7 @@ static struct virtio_consts vtnet_vi_con
        NULL,                   /* device-wide qnotify -- not used */
        pci_vtnet_cfgread,      /* read PCI config */
        pci_vtnet_cfgwrite,     /* write PCI config */
+       pci_vtnet_neg_features, /* apply negotiated features */
        VTNET_S_HOSTCAPS,       /* our capabilities */
 };
 
@@ -212,6 +217,8 @@ pci_vtnet_reset(void *vsc)
        pci_vtnet_rxwait(sc);
 
        sc->vsc_rx_ready = 0;
+       sc->rx_merge = 1;
+       sc->rx_vhdrlen = sizeof(struct virtio_net_rxhdr);
 
        /* now reset rings, MSI-X vectors, and negotiated capabilities */
        vi_reset_dev(&sc->vsc_vs);
@@ -253,14 +260,34 @@ pci_vtnet_tap_tx(struct pci_vtnet_softc 
  */
 static uint8_t dummybuf[2048];
 
+static __inline struct iovec *
+rx_iov_trim(struct iovec *iov, int *niov, int tlen)
+{
+       struct iovec *riov;
+
+       /* XXX short-cut: assume first segment is >= tlen */
+       assert(iov[0].iov_len >= tlen);
+
+       iov[0].iov_len -= tlen;
+       if (iov[0].iov_len == 0) {
+               assert(*niov > 1);
+               *niov -= 1;
+               riov = &iov[1];
+       } else {
+               iov[0].iov_base = (void *)((uintptr_t)iov[0].iov_base + tlen);
+               riov = &iov[0];
+       }
+
+       return (riov);
+}
+
 static void
 pci_vtnet_tap_rx(struct pci_vtnet_softc *sc)
 {
+       struct iovec iov[VTNET_MAXSEGS], *riov;
        struct vqueue_info *vq;
-       struct virtio_net_rxhdr *vrx;
-       uint8_t *buf;
-       int len;
-       struct iovec iov;
+       void *vrx;
+       int len, n;
 
        /*
         * Should never be called without a valid tap fd
@@ -296,21 +323,19 @@ pci_vtnet_tap_rx(struct pci_vtnet_softc 
 
        do {
                /*
-                * Get descriptor chain, which should have just
-                * one descriptor in it.
-                * ??? allow guests to use multiple descs?
+                * Get descriptor chain.
                 */
-               assert(vq_getchain(vq, &iov, 1, NULL) == 1);
+               n = vq_getchain(vq, iov, VTNET_MAXSEGS, NULL);
+               assert(n >= 1 && n <= VTNET_MAXSEGS);
 
                /*
                 * Get a pointer to the rx header, and use the
                 * data immediately following it for the packet buffer.
                 */
-               vrx = iov.iov_base;
-               buf = (uint8_t *)(vrx + 1);
+               vrx = iov[0].iov_base;
+               riov = rx_iov_trim(iov, &n, sc->rx_vhdrlen);
 
-               len = read(sc->vsc_tapfd, buf,
-                          iov.iov_len - sizeof(struct virtio_net_rxhdr));
+               len = readv(sc->vsc_tapfd, riov, n);
 
                if (len < 0 && errno == EWOULDBLOCK) {
                        /*
@@ -323,16 +348,21 @@ pci_vtnet_tap_rx(struct pci_vtnet_softc 
 
                /*
                 * The only valid field in the rx packet header is the
-                * number of buffers, which is always 1 without TSO
-                * support.
+                * number of buffers if merged rx bufs were negotiated.
                 */
-               memset(vrx, 0, sizeof(struct virtio_net_rxhdr));
-               vrx->vrh_bufs = 1;
+               memset(vrx, 0, sc->rx_vhdrlen);
+
+               if (sc->rx_merge) {
+                       struct virtio_net_rxhdr *vrxh;
+
+                       vrxh = vrx;
+                       vrxh->vrh_bufs = 1;
+               }
 
                /*
                 * Release this chain and handle more chains.
                 */
-               vq_relchain(vq, len + sizeof(struct virtio_net_rxhdr));
+               vq_relchain(vq, len + sc->rx_vhdrlen);
        } while (vq_has_descs(vq));
 
        /* Interrupt if needed, including for NOTIFY_ON_EMPTY. */
@@ -623,6 +653,8 @@ pci_vtnet_init(struct vmctx *ctx, struct
 
        sc->resetting = 0;
 
+       sc->rx_merge = 1;
+       sc->rx_vhdrlen = sizeof(struct virtio_net_rxhdr);
        sc->rx_in_progress = 0;
        pthread_mutex_init(&sc->rx_mtx, NULL); 
 
@@ -656,9 +688,10 @@ pci_vtnet_cfgwrite(void *vsc, int offset
                ptr = &sc->vsc_config.mac[offset];
                memcpy(ptr, &value, size);
        } else {
+               /* silently ignore other writes */
                DPRINTF(("vtnet: write to readonly reg %d\n\r", offset));
-               return (1);
        }
+
        return (0);
 }
 
@@ -673,6 +706,20 @@ pci_vtnet_cfgread(void *vsc, int offset,
        return (0);
 }
 
+static void
+pci_vtnet_neg_features(void *vsc, uint64_t negotiated_features)
+{
+       struct pci_vtnet_softc *sc = vsc;
+
+       sc->vsc_features = negotiated_features;
+
+       if (!(sc->vsc_features & VIRTIO_NET_F_MRG_RXBUF)) {
+               sc->rx_merge = 0;
+               /* non-merge rx header is 2 bytes shorter */
+               sc->rx_vhdrlen -= 2;
+       }
+}
+
 struct pci_devemu pci_de_vnet = {
        .pe_emu =       "virtio-net",
        .pe_init =      pci_vtnet_init,

Modified: stable/10/usr.sbin/bhyve/pci_virtio_rnd.c
==============================================================================
--- stable/10/usr.sbin/bhyve/pci_virtio_rnd.c   Tue Sep 16 18:02:24 2014        
(r271684)
+++ stable/10/usr.sbin/bhyve/pci_virtio_rnd.c   Tue Sep 16 19:08:54 2014        
(r271685)
@@ -80,6 +80,7 @@ static struct virtio_consts vtrnd_vi_con
        pci_vtrnd_notify,       /* device-wide qnotify */
        NULL,                   /* read virtio config */
        NULL,                   /* write virtio config */
+       NULL,                   /* apply negotiated features */
        0,                      /* our capabilities */
 };
 

Modified: stable/10/usr.sbin/bhyve/virtio.c
==============================================================================
--- stable/10/usr.sbin/bhyve/virtio.c   Tue Sep 16 18:02:24 2014        
(r271684)
+++ stable/10/usr.sbin/bhyve/virtio.c   Tue Sep 16 19:08:54 2014        
(r271685)
@@ -694,6 +694,9 @@ bad:
        switch (offset) {
        case VTCFG_R_GUESTCAP:
                vs->vs_negotiated_caps = value & vc->vc_hv_caps;
+               if (vc->vc_apply_features)
+                       (*vc->vc_apply_features)(DEV_SOFTC(vs),
+                           vs->vs_negotiated_caps);
                break;
        case VTCFG_R_PFN:
                if (vs->vs_curq >= vc->vc_nvq)

Modified: stable/10/usr.sbin/bhyve/virtio.h
==============================================================================
--- stable/10/usr.sbin/bhyve/virtio.h   Tue Sep 16 18:02:24 2014        
(r271684)
+++ stable/10/usr.sbin/bhyve/virtio.h   Tue Sep 16 19:08:54 2014        
(r271685)
@@ -352,6 +352,8 @@ struct virtio_consts {
                                        /* called to read config regs */
        int     (*vc_cfgwrite)(void *, int, int, uint32_t);
                                        /* called to write config regs */
+       void    (*vc_apply_features)(void *, uint64_t);
+                               /* called to apply negotiated features */
        uint64_t vc_hv_caps;            /* hypervisor-provided capabilities */
 };
 
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to