Module Name:    src
Committed By:   jdolecek
Date:           Mon Mar 30 15:31:52 UTC 2020

Modified Files:
        src/sys/arch/xen/xen: xennetback_xenbus.c

Log Message:
batch the GNTTABOP_copy hypervisor calls in xvif(4) when processing
DomU requests in xennetback_evthandler()

some 25% speed increase observed over the single-copy version


To generate a diff of this commit:
cvs rdiff -u -r1.88 -r1.89 src/sys/arch/xen/xen/xennetback_xenbus.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/xen/xen/xennetback_xenbus.c
diff -u src/sys/arch/xen/xen/xennetback_xenbus.c:1.88 src/sys/arch/xen/xen/xennetback_xenbus.c:1.89
--- src/sys/arch/xen/xen/xennetback_xenbus.c:1.88	Sun Mar 29 15:38:29 2020
+++ src/sys/arch/xen/xen/xennetback_xenbus.c	Mon Mar 30 15:31:52 2020
@@ -1,4 +1,4 @@
-/*      $NetBSD: xennetback_xenbus.c,v 1.88 2020/03/29 15:38:29 jdolecek Exp $      */
+/*      $NetBSD: xennetback_xenbus.c,v 1.89 2020/03/30 15:31:52 jdolecek Exp $      */
 
 /*
  * Copyright (c) 2006 Manuel Bouyer.
@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xennetback_xenbus.c,v 1.88 2020/03/29 15:38:29 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xennetback_xenbus.c,v 1.89 2020/03/30 15:31:52 jdolecek Exp $");
 
 #include "opt_xen.h"
 
@@ -178,6 +178,10 @@ static struct _pages_pool_free {
 	vaddr_t va;
 	paddr_t pa;
 } pages_pool_free[NB_XMIT_PAGES_BATCH];
+static struct _req_info {
+	int id;
+	int flags;
+} xstart_req[NB_XMIT_PAGES_BATCH];
 
 
 void
@@ -718,6 +722,71 @@ xennetback_tx_check_packet(const netif_t
 	return NULL;
 }
 
+static void
+xennetback_tx_copy_process(struct ifnet *ifp, struct xnetback_instance *xneti,
+	int queued)
+{
+	int i = 0;
+	gnttab_copy_t *gop;
+	struct mbuf *m;
+	struct _req_info *req;
+
+	/*
+	 * Copy the data and ack it. Delaying it until the mbuf is
+	 * freed will stall transmit.
+	 */
+	if (HYPERVISOR_grant_table_op(GNTTABOP_copy, xstart_gop_copy, queued)
+	    != 0) {
+		printf("%s: GNTTABOP_copy failed", ifp->if_xname);
+		goto abort;
+	}
+
+	for (; i < queued; i++) {
+		gop = &xstart_gop_copy[i];
+		m = mbufs_sent[i];
+		req = &xstart_req[i];
+
+		if (gop->status != GNTST_okay) {
+			printf("%s GNTTABOP_copy[%d] %d\n",
+			    ifp->if_xname, i, gop->status);
+			goto abort;
+		}
+
+		xennetback_tx_response(xneti, req->id, NETIF_RSP_OKAY);
+
+		if ((ifp->if_flags & IFF_PROMISC) == 0) {
+			struct ether_header *eh =
+			    mtod(m, struct ether_header *);
+			if (ETHER_IS_MULTICAST(eh->ether_dhost) == 0 &&
+			    memcmp(CLLADDR(ifp->if_sadl), eh->ether_dhost,
+			    ETHER_ADDR_LEN) != 0) {
+				m_freem(m);
+				continue; /* packet is not for us */
+			}
+		}
+
+		if (req->flags & NETTXF_csum_blank)
+			xennet_checksum_fill(ifp, m);
+		else if (req->flags & NETTXF_data_validated)
+			m->m_pkthdr.csum_flags = XN_M_CSUM_SUPPORTED;
+		m_set_rcvif(m, ifp);
+
+		if_percpuq_enqueue(ifp->if_percpuq, m);
+	}
+
+	return;
+
+abort:
+	for (; i < queued; i++) {
+		m = mbufs_sent[i];
+		req = &xstart_req[i];
+
+		m_freem(m);
+		xennetback_tx_response(xneti, req->id, NETIF_RSP_ERROR);
+		if_statinc(ifp, if_ierrors);
+	}
+}
+
 static int
 xennetback_evthandler(void *arg)
 {
@@ -727,9 +796,9 @@ xennetback_evthandler(void *arg)
 	struct mbuf *m;
 	int receive_pending;
 	RING_IDX req_cons;
-	gnttab_copy_t gop;
+	gnttab_copy_t *gop;
 	paddr_t pa;
-	int offset;
+	int offset, queued = 0;
 
 	XENPRINTF(("xennetback_evthandler "));
 	req_cons = xneti->xni_txring.req_cons;
@@ -796,68 +865,38 @@ xennetback_evthandler(void *arg)
 		    xneti->xni_if.if_xname, txreq.offset,
 		    txreq.size, txreq.id, MASK_NETIF_TX_IDX(req_cons)));
 
-		/*
-		 * Copy the data and ack it. Delaying it until the mbuf is
-		 * freed will stall transmit.
-		 */
 		xennetback_mbuf_addr(m, &pa, &offset);
-		memset(&gop, 0, sizeof(gop));
-		gop.flags = GNTCOPY_source_gref;
-		gop.len = txreq.size;
-
-		gop.source.u.ref = txreq.gref;
-		gop.source.offset = txreq.offset;
-		gop.source.domid = xneti->xni_domid;
-
-		gop.dest.offset = offset;
-		gop.dest.domid = DOMID_SELF;
-		gop.dest.u.gmfn = xpmap_ptom(pa) >> PAGE_SHIFT;
-
-		if (HYPERVISOR_grant_table_op(GNTTABOP_copy,
-		    &gop, 1) != 0) {
-			printf("%s: GNTTABOP_copy failed",
-			    ifp->if_xname);
-			m_freem(m);
-			xennetback_tx_response(xneti, txreq.id,
-			    NETIF_RSP_ERROR);
-			if_statinc(ifp, if_ierrors);
-			continue;
-		}
-		if (gop.status != GNTST_okay) {
-			printf("%s GNTTABOP_copy %d\n",
-			    ifp->if_xname, gop.status);
-			m_freem(m);
-			xennetback_tx_response(xneti, txreq.id,
-			    NETIF_RSP_ERROR);
-			if_statinc(ifp, if_ierrors);
-			continue;
-		}
 
-		if ((ifp->if_flags & IFF_PROMISC) == 0) {
-			struct ether_header *eh =
-			    mtod(m, struct ether_header *);
-			if (ETHER_IS_MULTICAST(eh->ether_dhost) == 0 &&
-			    memcmp(CLLADDR(ifp->if_sadl), eh->ether_dhost,
-			    ETHER_ADDR_LEN) != 0) {
-				m_freem(m);
-				xennetback_tx_response(xneti, txreq.id,
-				    NETIF_RSP_OKAY);
-				continue; /* packet is not for us */
-			}
-		}
+		/* Queue for the copy */
+		gop = &xstart_gop_copy[queued];
+		memset(gop, 0, sizeof(*gop));
+		gop->flags = GNTCOPY_source_gref;
+		gop->len = txreq.size;
+
+		gop->source.u.ref = txreq.gref;
+		gop->source.offset = txreq.offset;
+		gop->source.domid = xneti->xni_domid;
+
+		gop->dest.offset = offset;
+		gop->dest.domid = DOMID_SELF;
+		gop->dest.u.gmfn = xpmap_ptom(pa) >> PAGE_SHIFT;
 
 		m->m_len = m->m_pkthdr.len = txreq.size;
-		xennetback_tx_response(xneti, txreq.id,
-		    NETIF_RSP_OKAY);
+		mbufs_sent[queued] = m;
 
-		if (txreq.flags & NETTXF_csum_blank)
-			xennet_checksum_fill(ifp, m);
-		else if (txreq.flags & NETTXF_data_validated)
-			m->m_pkthdr.csum_flags = XN_M_CSUM_SUPPORTED;
-		m_set_rcvif(m, ifp);
+		xstart_req[queued].id = txreq.id;
+		xstart_req[queued].flags = txreq.flags;
 
-		if_percpuq_enqueue(ifp->if_percpuq, m);
+		queued++;
+
+		KASSERT(queued <= NB_XMIT_PAGES_BATCH);
+		if (queued == NB_XMIT_PAGES_BATCH) {
+			xennetback_tx_copy_process(ifp, xneti, queued);
+			queued = 0;
+		}
 	}
+	if (queued > 0)
+		xennetback_tx_copy_process(ifp, xneti, queued);
 	xen_rmb(); /* be sure to read the request before updating pointer */
 	xneti->xni_txring.req_cons = req_cons;
 	xen_wmb();

Reply via email to