Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 19 Sep 2017 06:38:57 +0000 (UTC)
From:      Sepherosa Ziehau <sephe@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r323728 - head/sys/dev/hyperv/netvsc
Message-ID:  <201709190638.v8J6cvP7088752@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: sephe
Date: Tue Sep 19 06:38:57 2017
New Revision: 323728
URL: https://svnweb.freebsd.org/changeset/base/323728

Log:
  hyperv/hn: Fix MTU setting
  
  - Add size of an ethernet header to the value configured to NVS.  This
    does not seem to have any effects if MTU is 1500, but fix hypervisor
    side's setting if MTU > 1500.
  - Override the MTU setting according to the view from the hypervisor
    side.
  
  MFC after:	1 week
  Sponsored by:	Microsoft
  Differential Revision:	https://reviews.freebsd.org/D12352

Modified:
  head/sys/dev/hyperv/netvsc/hn_nvs.c
  head/sys/dev/hyperv/netvsc/hn_rndis.c
  head/sys/dev/hyperv/netvsc/hn_rndis.h
  head/sys/dev/hyperv/netvsc/if_hn.c

Modified: head/sys/dev/hyperv/netvsc/hn_nvs.c
==============================================================================
--- head/sys/dev/hyperv/netvsc/hn_nvs.c	Tue Sep 19 06:29:38 2017	(r323727)
+++ head/sys/dev/hyperv/netvsc/hn_nvs.c	Tue Sep 19 06:38:57 2017	(r323728)
@@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/systm.h>
 #include <sys/taskqueue.h>
 
+#include <net/ethernet.h>
 #include <net/if.h>
 #include <net/if_var.h>
 #include <net/if_media.h>
@@ -503,7 +504,7 @@ hn_nvs_conf_ndis(struct hn_softc *sc, int mtu)
 
 	memset(&conf, 0, sizeof(conf));
 	conf.nvs_type = HN_NVS_TYPE_NDIS_CONF;
-	conf.nvs_mtu = mtu;
+	conf.nvs_mtu = mtu + ETHER_HDR_LEN;
 	conf.nvs_caps = HN_NVS_NDIS_CONF_VLAN;
 	if (sc->hn_nvs_ver >= HN_NVS_VERSION_5)
 		conf.nvs_caps |= HN_NVS_NDIS_CONF_SRIOV;

Modified: head/sys/dev/hyperv/netvsc/hn_rndis.c
==============================================================================
--- head/sys/dev/hyperv/netvsc/hn_rndis.c	Tue Sep 19 06:29:38 2017	(r323727)
+++ head/sys/dev/hyperv/netvsc/hn_rndis.c	Tue Sep 19 06:38:57 2017	(r323728)
@@ -188,6 +188,24 @@ hn_rndis_get_linkstatus(struct hn_softc *sc, uint32_t 
 	return (0);
 }
 
+int
+hn_rndis_get_mtu(struct hn_softc *sc, uint32_t *mtu)
+{
+	size_t size;
+	int error;
+
+	size = sizeof(*mtu);
+	error = hn_rndis_query(sc, OID_GEN_MAXIMUM_FRAME_SIZE, NULL, 0,
+	    mtu, &size);
+	if (error)
+		return (error);
+	if (size != sizeof(uint32_t)) {
+		if_printf(sc->hn_ifp, "invalid mtu len %zu\n", size);
+		return (EINVAL);
+	}
+	return (0);
+}
+
 static const void *
 hn_rndis_xact_exec1(struct hn_softc *sc, struct vmbus_xact *xact, size_t reqlen,
     struct hn_nvs_sendctx *sndc, size_t *comp_len)

Modified: head/sys/dev/hyperv/netvsc/hn_rndis.h
==============================================================================
--- head/sys/dev/hyperv/netvsc/hn_rndis.h	Tue Sep 19 06:29:38 2017	(r323727)
+++ head/sys/dev/hyperv/netvsc/hn_rndis.h	Tue Sep 19 06:38:57 2017	(r323728)
@@ -41,6 +41,7 @@ int		hn_rndis_get_eaddr(struct hn_softc *sc, uint8_t *
 /* link_status: NDIS_MEDIA_STATE_ */
 int		hn_rndis_get_linkstatus(struct hn_softc *sc,
 		    uint32_t *link_status);
+int		hn_rndis_get_mtu(struct hn_softc *sc, uint32_t *mtu);
 /* filter: NDIS_PACKET_TYPE_. */
 int		hn_rndis_set_rxfilter(struct hn_softc *sc, uint32_t filter);
 void		hn_rndis_rx_ctrl(struct hn_softc *sc, const void *data,

Modified: head/sys/dev/hyperv/netvsc/if_hn.c
==============================================================================
--- head/sys/dev/hyperv/netvsc/if_hn.c	Tue Sep 19 06:29:38 2017	(r323727)
+++ head/sys/dev/hyperv/netvsc/if_hn.c	Tue Sep 19 06:38:57 2017	(r323728)
@@ -2003,6 +2003,7 @@ hn_attach(device_t dev)
 	uint8_t eaddr[ETHER_ADDR_LEN];
 	struct ifnet *ifp = NULL;
 	int error, ring_cnt, tx_ring_cnt;
+	uint32_t mtu;
 
 	sc->hn_dev = dev;
 	sc->hn_prichan = vmbus_get_channel(dev);
@@ -2159,6 +2160,12 @@ hn_attach(device_t dev)
 	if (error)
 		goto failed;
 
+	error = hn_rndis_get_mtu(sc, &mtu);
+	if (error)
+		mtu = ETHERMTU;
+	else if (bootverbose)
+		device_printf(dev, "RNDIS mtu %u\n", mtu);
+
 #if __FreeBSD_version >= 1100099
 	if (sc->hn_rx_ring_inuse > 1) {
 		/*
@@ -2343,6 +2350,10 @@ hn_attach(device_t dev)
 		if_printf(ifp, "TSO segcnt %u segsz %u\n",
 		    ifp->if_hw_tsomaxsegcount, ifp->if_hw_tsomaxsegsize);
 	}
+	if (mtu < ETHERMTU) {
+		if_printf(ifp, "fixup mtu %u -> %u\n", ifp->if_mtu, mtu);
+		ifp->if_mtu = mtu;
+	}
 
 	/* Inform the upper layer about the long frame support. */
 	ifp->if_hdrlen = sizeof(struct ether_vlan_header);
@@ -3587,6 +3598,7 @@ hn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
 	int mask, error = 0;
 	struct ifrsskey *ifrk;
 	struct ifrsshash *ifrh;
+	uint32_t mtu;
 
 	switch (cmd) {
 	case SIOCSIFMTU:
@@ -3650,11 +3662,23 @@ hn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
 			break;
 		}
 
+		error = hn_rndis_get_mtu(sc, &mtu);
+		if (error)
+			mtu = ifr->ifr_mtu;
+		else if (bootverbose)
+			if_printf(ifp, "RNDIS mtu %u\n", mtu);
+
 		/*
 		 * Commit the requested MTU, after the synthetic parts
 		 * have been successfully attached.
 		 */
-		ifp->if_mtu = ifr->ifr_mtu;
+		if (mtu >= ifr->ifr_mtu) {
+			mtu = ifr->ifr_mtu;
+		} else {
+			if_printf(ifp, "fixup mtu %d -> %u\n",
+			    ifr->ifr_mtu, mtu);
+		}
+		ifp->if_mtu = mtu;
 
 		/*
 		 * Synthetic parts' reattach may change the chimney



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