Date: Thu, 2 Jun 2016 11:21:00 +0000 (UTC) From: =?UTF-8?Q?Roger_Pau_Monn=c3=a9?= <royger@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r301201 - head/sys/dev/xen/netfront Message-ID: <201606021121.u52BL0jZ048331@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
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@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;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201606021121.u52BL0jZ048331>