svn commit: r301201 - head/sys/dev/xen/netfront
Roger Pau Monné
royger at FreeBSD.org
Thu Jun 2 11:21:01 UTC 2016
Author: royger
Date: Thu Jun 2 11:21:00 2016
New Revision: 301201
URL: https://svnweb.freebsd.org/changeset/base/301201
Log:
xen-netfront: perform an interface reset when changing options
The PV backend will only pick the new options when the interface is detached
and reattached again, so perform a full reset when changing options. This is
very fast, and should not be noticeable by the user.
Reviewed by: Wei Liu <wei.liu2 at citrix.com>
Sponsored by: Citrix Systems R&D
Differential revision: https://reviews.freebsd.org/D6658
Modified:
head/sys/dev/xen/netfront/netfront.c
Modified: head/sys/dev/xen/netfront/netfront.c
==============================================================================
--- head/sys/dev/xen/netfront/netfront.c Thu Jun 2 11:19:16 2016 (r301200)
+++ head/sys/dev/xen/netfront/netfront.c Thu Jun 2 11:21:00 2016 (r301201)
@@ -237,7 +237,7 @@ struct netfront_info {
struct ifmedia sc_media;
- bool xn_resume;
+ bool xn_reset;
};
struct netfront_rx_info {
@@ -458,7 +458,6 @@ netfront_resume(device_t dev)
{
struct netfront_info *info = device_get_softc(dev);
- info->xn_resume = true;
netif_disconnect_backend(info);
return (0);
}
@@ -590,10 +589,19 @@ talk_to_backend(device_t dev, struct net
message = "writing feature-sg";
goto abort_transaction;
}
- err = xs_printf(xst, node, "feature-gso-tcpv4", "%d", 1);
- if (err != 0) {
- message = "writing feature-gso-tcpv4";
- goto abort_transaction;
+ if ((info->xn_ifp->if_capenable & IFCAP_LRO) != 0) {
+ err = xs_printf(xst, node, "feature-gso-tcpv4", "%d", 1);
+ if (err != 0) {
+ message = "writing feature-gso-tcpv4";
+ goto abort_transaction;
+ }
+ }
+ if ((info->xn_ifp->if_capenable & IFCAP_RXCSUM) == 0) {
+ err = xs_printf(xst, node, "feature-no-csum-offload", "%d", 1);
+ if (err != 0) {
+ message = "writing feature-no-csum-offload";
+ goto abort_transaction;
+ }
}
err = xs_transaction_end(xst, 0);
@@ -960,7 +968,6 @@ netfront_backend_changed(device_t dev, X
case XenbusStateInitialising:
case XenbusStateInitialised:
case XenbusStateUnknown:
- case XenbusStateClosed:
case XenbusStateReconfigured:
case XenbusStateReconfiguring:
break;
@@ -974,6 +981,13 @@ netfront_backend_changed(device_t dev, X
case XenbusStateClosing:
xenbus_set_state(dev, XenbusStateClosed);
break;
+ case XenbusStateClosed:
+ if (sc->xn_reset) {
+ netif_disconnect_backend(sc);
+ xenbus_set_state(dev, XenbusStateInitialising);
+ sc->xn_reset = false;
+ }
+ break;
case XenbusStateConnected:
#ifdef INET
netfront_send_fake_arp(dev, sc);
@@ -1739,11 +1753,14 @@ xn_ioctl(struct ifnet *ifp, u_long cmd,
{
struct netfront_info *sc = ifp->if_softc;
struct ifreq *ifr = (struct ifreq *) data;
+ device_t dev;
#ifdef INET
struct ifaddr *ifa = (struct ifaddr *)data;
#endif
-
int mask, error = 0;
+
+ dev = sc->xbdev;
+
switch(cmd) {
case SIOCSIFADDR:
#ifdef INET
@@ -1820,6 +1837,31 @@ xn_ioctl(struct ifnet *ifp, u_long cmd,
ifp->if_capenable ^= IFCAP_LRO;
}
+ /*
+ * We must reset the interface so the backend picks up the
+ * new features.
+ */
+ XN_LOCK(sc);
+ netfront_carrier_off(sc);
+ sc->xn_reset = true;
+ /*
+ * NB: the pending packet queue is not flushed, since
+ * the interface should still support the old options.
+ */
+ XN_UNLOCK(sc);
+ /*
+ * Delete the xenstore nodes that export features.
+ *
+ * NB: There's a xenbus state called
+ * "XenbusStateReconfiguring", which is what we should set
+ * here. Sadly none of the backends know how to handle it,
+ * and simply disconnect from the frontend, so we will just
+ * switch back to XenbusStateInitialising in order to force
+ * a reconnection.
+ */
+ xs_rm(XST_NIL, xenbus_get_node(dev), "feature-gso-tcpv4");
+ xs_rm(XST_NIL, xenbus_get_node(dev), "feature-no-csum-offload");
+ xenbus_set_state(dev, XenbusStateClosing);
break;
case SIOCADDMULTI:
case SIOCDELMULTI:
@@ -1967,6 +2009,20 @@ xn_query_features(struct netfront_info *
printf(" feature-gso-tcp4");
}
+ /*
+ * HW CSUM offload is assumed to be available unless
+ * feature-no-csum-offload is set in xenstore.
+ */
+ if (xs_scanf(XST_NIL, xenbus_get_otherend_path(np->xbdev),
+ "feature-no-csum-offload", NULL, "%d", &val) != 0)
+ val = 0;
+
+ np->xn_ifp->if_capabilities |= IFCAP_HWCSUM;
+ if (val) {
+ np->xn_ifp->if_capabilities &= ~(IFCAP_HWCSUM);
+ printf(" feature-no-csum-offload");
+ }
+
printf("\n");
}
@@ -1977,50 +2033,50 @@ xn_configure_features(struct netfront_in
#if (defined(INET) || defined(INET6))
int i;
#endif
+ struct ifnet *ifp;
+ ifp = np->xn_ifp;
err = 0;
- if (np->xn_resume &&
- ((np->xn_ifp->if_capenable & np->xn_ifp->if_capabilities)
- == np->xn_ifp->if_capenable)) {
+ if ((ifp->if_capenable & ifp->if_capabilities) == ifp->if_capenable) {
/* Current options are available, no need to do anything. */
return (0);
}
/* Try to preserve as many options as possible. */
- if (np->xn_resume)
- cap_enabled = np->xn_ifp->if_capenable;
- else
- cap_enabled = UINT_MAX;
+ cap_enabled = ifp->if_capenable;
+ ifp->if_capenable = ifp->if_hwassist = 0;
#if (defined(INET) || defined(INET6))
- for (i = 0; i < np->num_queues; i++)
- if ((np->xn_ifp->if_capenable & IFCAP_LRO) ==
- (cap_enabled & IFCAP_LRO))
+ if ((cap_enabled & IFCAP_LRO) != 0)
+ for (i = 0; i < np->num_queues; i++)
tcp_lro_free(&np->rxq[i].lro);
-#endif
- np->xn_ifp->if_capenable =
- np->xn_ifp->if_capabilities & ~(IFCAP_LRO|IFCAP_TSO4) & cap_enabled;
- np->xn_ifp->if_hwassist &= ~CSUM_TSO;
-#if (defined(INET) || defined(INET6))
- for (i = 0; i < np->num_queues; i++) {
- if (xn_enable_lro && (np->xn_ifp->if_capabilities & IFCAP_LRO) ==
- (cap_enabled & IFCAP_LRO)) {
+ if (xn_enable_lro &&
+ (ifp->if_capabilities & cap_enabled & IFCAP_LRO) != 0) {
+ ifp->if_capenable |= IFCAP_LRO;
+ for (i = 0; i < np->num_queues; i++) {
err = tcp_lro_init(&np->rxq[i].lro);
if (err != 0) {
- device_printf(np->xbdev, "LRO initialization failed\n");
- } else {
- np->rxq[i].lro.ifp = np->xn_ifp;
- np->xn_ifp->if_capenable |= IFCAP_LRO;
+ device_printf(np->xbdev,
+ "LRO initialization failed\n");
+ ifp->if_capenable &= ~IFCAP_LRO;
+ break;
}
+ np->rxq[i].lro.ifp = ifp;
}
}
- if ((np->xn_ifp->if_capabilities & IFCAP_TSO4) ==
- (cap_enabled & IFCAP_TSO4)) {
- np->xn_ifp->if_capenable |= IFCAP_TSO4;
- np->xn_ifp->if_hwassist |= CSUM_TSO;
+ if ((ifp->if_capabilities & cap_enabled & IFCAP_TSO4) != 0) {
+ ifp->if_capenable |= IFCAP_TSO4;
+ ifp->if_hwassist |= CSUM_TSO;
}
#endif
+ if ((ifp->if_capabilities & cap_enabled & IFCAP_TXCSUM) != 0) {
+ ifp->if_capenable |= IFCAP_TXCSUM;
+ ifp->if_hwassist |= CSUM_TCP|CSUM_UDP;
+ }
+ if ((ifp->if_capabilities & cap_enabled & IFCAP_RXCSUM) != 0)
+ ifp->if_capenable |= IFCAP_RXCSUM;
+
return (err);
}
@@ -2169,7 +2225,9 @@ create_netdev(device_t dev)
ifp->if_init = xn_ifinit;
ifp->if_hwassist = XN_CSUM_FEATURES;
- ifp->if_capabilities = IFCAP_HWCSUM;
+ /* Enable all supported features at device creation. */
+ ifp->if_capenable = ifp->if_capabilities =
+ IFCAP_HWCSUM|IFCAP_TSO4|IFCAP_LRO;
ifp->if_hw_tsomax = 65536 - (ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN);
ifp->if_hw_tsomaxsegcount = MAX_TX_REQ_FRAGS;
ifp->if_hw_tsomaxsegsize = PAGE_SIZE;
More information about the svn-src-all
mailing list