hyperv: Add processing of MTU reduced by the host
authorHaiyang Zhang <haiyangz@microsoft.com>
Wed, 12 Nov 2014 22:07:44 +0000 (14:07 -0800)
committerDavid S. Miller <davem@davemloft.net>
Wed, 12 Nov 2014 21:21:36 +0000 (16:21 -0500)
If the host uses packet encapsulation feature, the MTU may be reduced by the
host due to headroom reservation for encapsulation. This patch handles this
new MTU value.

Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/hyperv/netvsc.c
drivers/net/hyperv/netvsc_drv.c
drivers/net/hyperv/rndis_filter.c

index 7d76c9523395e5b5137784189d902d9cb1ecaed5..6b463117dcaca45f6130a0b6f4573d8946bc41ec 100644 (file)
@@ -440,7 +440,8 @@ static int negotiate_nvsp_ver(struct hv_device *device,
        /* NVSPv2 only: Send NDIS config */
        memset(init_packet, 0, sizeof(struct nvsp_message));
        init_packet->hdr.msg_type = NVSP_MSG2_TYPE_SEND_NDIS_CONFIG;
-       init_packet->msg.v2_msg.send_ndis_config.mtu = net_device->ndev->mtu;
+       init_packet->msg.v2_msg.send_ndis_config.mtu = net_device->ndev->mtu +
+                                                      ETH_HLEN;
        init_packet->msg.v2_msg.send_ndis_config.capability.ieee8021q = 1;
 
        ret = vmbus_sendpacket(device->channel, init_packet,
index 3295e4ee9dbb19ee821370833e545ac944366610..15d82eda0baf4141465addd6207c6202f09f2543 100644 (file)
@@ -699,9 +699,10 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu)
                return -ENODEV;
 
        if (nvdev->nvsp_version >= NVSP_PROTOCOL_VERSION_2)
-               limit = NETVSC_MTU;
+               limit = NETVSC_MTU - ETH_HLEN;
 
-       if (mtu < 68 || mtu > limit)
+       /* Hyper-V hosts don't support MTU < ETH_DATA_LEN (1500) */
+       if (mtu < ETH_DATA_LEN || mtu > limit)
                return -EINVAL;
 
        nvdev->start_remove = true;
index ccce6f24b009c797b777f94d690e1c76e382e136..7b2c5d1e9bad1b21747d4310324d8d51e7a3000f 100644 (file)
@@ -998,6 +998,7 @@ int rndis_filter_device_add(struct hv_device *dev,
        int t;
        struct ndis_recv_scale_cap rsscap;
        u32 rsscap_size = sizeof(struct ndis_recv_scale_cap);
+       u32 mtu, size;
 
        rndis_device = get_rndis_device();
        if (!rndis_device)
@@ -1029,6 +1030,14 @@ int rndis_filter_device_add(struct hv_device *dev,
                return ret;
        }
 
+       /* Get the MTU from the host */
+       size = sizeof(u32);
+       ret = rndis_filter_query_device(rndis_device,
+                                       RNDIS_OID_GEN_MAXIMUM_FRAME_SIZE,
+                                       &mtu, &size);
+       if (ret == 0 && size == sizeof(u32))
+               net_device->ndev->mtu = mtu;
+
        /* Get the mac address */
        ret = rndis_filter_query_device_mac(rndis_device);
        if (ret != 0) {