Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 21 Sep 2011 00:15:29 +0000 (UTC)
From:      "Justin T. Gibbs" <gibbs@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r225709 - head/sys/dev/xen/netfront
Message-ID:  <201109210015.p8L0FTIH050962@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: gibbs
Date: Wed Sep 21 00:15:29 2011
New Revision: 225709
URL: http://svn.freebsd.org/changeset/base/225709

Log:
  Update netfront so that it queries and honors published
  back-end features.
  
  sys/dev/xen/netfront/netfront.c:
  	o Add xn_query_features() which reads the XenStore and
  	  records the TSO, LRO, and chained ring-request support
  	  of the backend.
  	o Rename xn_configure_lro() to xn_configure_features() and
  	  use this routine to manage the setup of TSO, LRO, and
  	  checksum offload.
  	o In create_netdev(), initialize if_capabilities and
  	  if_hwassist to the capabilities found on all backends.
  	  Delegate configuration of if_capenable and the TSO flag
  	  if if_hwassist to xn_configure_features().
  
  Reported by:	Hugo Silva (fix inspired by patch provided)
  Approved by:	re
  MFC after:	1 week

Modified:
  head/sys/dev/xen/netfront/netfront.c

Modified: head/sys/dev/xen/netfront/netfront.c
==============================================================================
--- head/sys/dev/xen/netfront/netfront.c	Wed Sep 21 00:13:04 2011	(r225708)
+++ head/sys/dev/xen/netfront/netfront.c	Wed Sep 21 00:15:29 2011	(r225709)
@@ -92,7 +92,8 @@ __FBSDID("$FreeBSD$");
 
 #include "xenbus_if.h"
 
-#define XN_CSUM_FEATURES	(CSUM_TCP | CSUM_UDP | CSUM_TSO)
+/* Features supported by all backends.  TSO and LRO can be negotiated */
+#define XN_CSUM_FEATURES	(CSUM_TCP | CSUM_UDP)
 
 #define NET_TX_RING_SIZE __RING_SIZE((netif_tx_sring_t *)0, PAGE_SIZE)
 #define NET_RX_RING_SIZE __RING_SIZE((netif_rx_sring_t *)0, PAGE_SIZE)
@@ -159,7 +160,8 @@ static int  xn_ioctl(struct ifnet *, u_l
 static void xn_ifinit_locked(struct netfront_info *);
 static void xn_ifinit(void *);
 static void xn_stop(struct netfront_info *);
-static int xn_configure_lro(struct netfront_info *np);
+static void xn_query_features(struct netfront_info *np);
+static int  xn_configure_features(struct netfront_info *np);
 #ifdef notyet
 static void xn_watchdog(struct ifnet *);
 #endif
@@ -262,6 +264,7 @@ struct netfront_info {
 	u_int irq;
 	u_int copying_receiver;
 	u_int carrier;
+	u_int maxfrags;
 		
 	/* Receive-ring batched refills. */
 #define RX_MIN_TARGET 32
@@ -1526,7 +1529,7 @@ xn_assemble_tx_request(struct netfront_i
 	 * deal with nfrags > MAX_TX_REQ_FRAGS, which is a quirk of
 	 * the Linux network stack.
 	 */
-	if (nfrags > MAX_TX_REQ_FRAGS) {
+	if (nfrags > sc->maxfrags) {
 		m = m_defrag(m_head, M_DONTWAIT);
 		if (!m) {
 			/*
@@ -1943,10 +1946,11 @@ network_connect(struct netfront_info *np
 		return (error);
 	
 	/* Step 1: Reinitialise variables. */
+	xn_query_features(np);
+	xn_configure_features(np);
 	netif_release_tx_bufs(np);
 
 	/* Step 2: Rebuild the RX buffer freelist and the RX ring itself. */
-	xn_configure_lro(np);
 	for (requeue_idx = 0, i = 0; i < NET_RX_RING_SIZE; i++) {
 		struct mbuf *m;
 		u_long pfn;
@@ -2011,26 +2015,63 @@ show_device(struct netfront_info *sc)
 #endif
 }
 
+static void
+xn_query_features(struct netfront_info *np)
+{
+	int val;
+
+	device_printf(np->xbdev, "backend features:");
+
+	if (xs_scanf(XST_NIL, xenbus_get_otherend_path(np->xbdev),
+		"feature-sg", NULL, "%d", &val) < 0)
+		val = 0;
+
+	np->maxfrags = 1;
+	if (val) {
+		np->maxfrags = MAX_TX_REQ_FRAGS;
+		printf(" feature-sg");
+	}
+
+	if (xs_scanf(XST_NIL, xenbus_get_otherend_path(np->xbdev),
+		"feature-gso-tcpv4", NULL, "%d", &val) < 0)
+		val = 0;
+
+	np->xn_ifp->if_capabilities &= ~(IFCAP_TSO4|IFCAP_LRO);
+	if (val) {
+		np->xn_ifp->if_capabilities |= IFCAP_TSO4|IFCAP_LRO;
+		printf(" feature-gso-tcp4");
+	}
+
+	printf("\n");
+}
+
 static int
-xn_configure_lro(struct netfront_info *np)
+xn_configure_features(struct netfront_info *np)
 {
 	int err;
 
 	err = 0;
 #if __FreeBSD_version >= 700000
-	if ((np->xn_ifp->if_capabilities & IFCAP_LRO) != 0)
+	if ((np->xn_ifp->if_capenable & IFCAP_LRO) != 0)
 		tcp_lro_free(&np->xn_lro);
-	np->xn_ifp->if_capabilities &= ~IFCAP_LRO;
-	if (xn_enable_lro) {
+#endif
+    	np->xn_ifp->if_capenable =
+	    np->xn_ifp->if_capabilities & ~(IFCAP_LRO|IFCAP_TSO4);
+	np->xn_ifp->if_hwassist &= ~CSUM_TSO;
+#if __FreeBSD_version >= 700000
+	if (xn_enable_lro && (np->xn_ifp->if_capabilities & IFCAP_LRO) != 0) {
 		err = tcp_lro_init(&np->xn_lro);
 		if (err) {
 			device_printf(np->xbdev, "LRO initialization failed\n");
 		} else {
 			np->xn_lro.ifp = np->xn_ifp;
-			np->xn_ifp->if_capabilities |= IFCAP_LRO;
+			np->xn_ifp->if_capenable |= IFCAP_LRO;
 		}
 	}
-    	np->xn_ifp->if_capenable = np->xn_ifp->if_capabilities;
+	if ((np->xn_ifp->if_capabilities & IFCAP_TSO4) != 0) {
+		np->xn_ifp->if_capenable |= IFCAP_TSO4;
+		np->xn_ifp->if_hwassist |= CSUM_TSO;
+	}
 #endif
 	return (err);
 }
@@ -2059,7 +2100,7 @@ create_netdev(device_t dev)
 	np->rx_target     = RX_MIN_TARGET;
 	np->rx_min_target = RX_MIN_TARGET;
 	np->rx_max_target = RX_MAX_TARGET;
-	
+
 	/* Initialise {tx,rx}_skbs to be a free chain containing every entry. */
 	for (i = 0; i <= NET_TX_RING_SIZE; i++) {
 		np->tx_mbufs[i] = (void *) ((u_long) i+1);
@@ -2109,11 +2150,6 @@ create_netdev(device_t dev)
 	
     	ifp->if_hwassist = XN_CSUM_FEATURES;
     	ifp->if_capabilities = IFCAP_HWCSUM;
-#if __FreeBSD_version >= 700000
-	ifp->if_capabilities |= IFCAP_TSO4;
-#endif
-    	ifp->if_capenable = ifp->if_capabilities;
-	xn_configure_lro(np);
 	
     	ether_ifattach(ifp, np->mac);
     	callout_init(&np->xn_stat_ch, CALLOUT_MPSAFE);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201109210015.p8L0FTIH050962>