svn commit: r361696 - head/sys/dev/netmap

Vincenzo Maffione vmaffione at FreeBSD.org
Mon Jun 1 16:10:45 UTC 2020


Author: vmaffione
Date: Mon Jun  1 16:10:44 2020
New Revision: 361696
URL: https://svnweb.freebsd.org/changeset/base/361696

Log:
  netmap: vtnet: fix RX virtqueue initialization bug
  
  The vtnet_netmap_rxq_populate() function erroneously assumed
  that kring->nr_hwcur = 0, i.e. the kring was in the initial
  state. However, this is not always the case: for example,
  when a vtnet reinit is triggered by some changes in the
  interface flags or capenable.
  This patch changes the behaviour of vtnet_netmap_kring_refill()
  so that it always starts publishing the netmap buffers starting
  from the current value of kring->nr_hwcur.
  
  MFC after:	1 week

Modified:
  head/sys/dev/netmap/if_vtnet_netmap.h

Modified: head/sys/dev/netmap/if_vtnet_netmap.h
==============================================================================
--- head/sys/dev/netmap/if_vtnet_netmap.h	Mon Jun  1 15:58:22 2020	(r361695)
+++ head/sys/dev/netmap/if_vtnet_netmap.h	Mon Jun  1 16:10:44 2020	(r361696)
@@ -232,14 +232,20 @@ vtnet_netmap_txsync(struct netmap_kring *kring, int fl
 	return 0;
 }
 
+/*
+ * Publish (up to) num netmap receive buffers to the host,
+ * starting from the first one that the user made available
+ * (kring->nr_hwcur).
+ */
 static int
-vtnet_netmap_kring_refill(struct netmap_kring *kring, u_int nm_i, u_int head)
+vtnet_netmap_kring_refill(struct netmap_kring *kring, u_int num)
 {
 	struct netmap_adapter *na = kring->na;
 	struct ifnet *ifp = na->ifp;
 	struct netmap_ring *ring = kring->ring;
 	u_int ring_nr = kring->ring_id;
 	u_int const lim = kring->nkr_num_slots - 1;
+	u_int nm_i = kring->nr_hwcur;
 
 	/* device-specific */
 	struct vtnet_softc *sc = ifp->if_softc;
@@ -250,7 +256,7 @@ vtnet_netmap_kring_refill(struct netmap_kring *kring, 
 	struct sglist_seg ss[2];
 	struct sglist sg = { ss, 0, 0, 2 };
 
-	for (; nm_i != head; nm_i = nm_next(nm_i, lim)) {
+	for (; num > 0; nm_i = nm_next(nm_i, lim), num--) {
 		struct netmap_slot *slot = &ring->slot[nm_i];
 		uint64_t paddr;
 		void *addr = PNMB(na, slot, &paddr);
@@ -302,10 +308,11 @@ vtnet_netmap_rxq_populate(struct vtnet_rxq *rxq)
 			kring->nr_pending_mode == NKR_NETMAP_ON))
 		return -1;
 
-	/* Expose all the RX netmap buffers. Note that the number of
-	 * netmap slots in the RX ring matches the maximum number of
-	 * 2-elements sglist that the RX virtqueue can accommodate. */
-	error = vtnet_netmap_kring_refill(kring, 0, na->num_rx_desc);
+	/* Expose all the RX netmap buffers we can. In case of no indirect
+	 * buffers, the number of netmap slots in the RX ring matches the
+	 * maximum number of 2-elements sglist that the RX virtqueue can
+	 * accommodate. */
+	error = vtnet_netmap_kring_refill(kring, na->num_rx_desc);
 	virtqueue_notify(rxq->vtnrx_vq);
 
 	return error < 0 ? ENXIO : 0;
@@ -381,7 +388,12 @@ vtnet_netmap_rxsync(struct netmap_kring *kring, int fl
 	 */
 	nm_i = kring->nr_hwcur; /* netmap ring index */
 	if (nm_i != head) {
-		int nm_j = vtnet_netmap_kring_refill(kring, nm_i, head);
+		int howmany = head - nm_i;
+		int nm_j;
+
+		if (howmany < 0)
+			howmany += kring->nkr_num_slots;
+		nm_j = vtnet_netmap_kring_refill(kring, howmany);
 		if (nm_j < 0)
 			return nm_j;
 		kring->nr_hwcur = nm_j;


More information about the svn-src-head mailing list