#define NDIS_TCP_LARGE_SEND_OFFLOAD_IPV4       0
 #define NDIS_TCP_LARGE_SEND_OFFLOAD_IPV6       1
 
+#define VERSION_4_OFFLOAD_SIZE                 22
 /*
  * New offload OIDs for NDIS 6
  */
 
                csum_info->transmit.tcp_checksum = 1;
                csum_info->transmit.tcp_header_offset = hdr_offset;
        } else if (net_trans_info & INFO_UDP) {
-               csum_info->transmit.udp_checksum = 1;
+               /* UDP checksum offload is not supported on ws2008r2.
+                * Furthermore, on ws2012 and ws2012r2, there are some
+                * issues with udp checksum offload from Linux guests.
+                * (these are host issues).
+                * For now compute the checksum here.
+                */
+               struct udphdr *uh;
+               u16 udp_len;
+
+               ret = skb_cow_head(skb, 0);
+               if (ret)
+                       goto drop;
+
+               uh = udp_hdr(skb);
+               udp_len = ntohs(uh->len);
+               uh->check = 0;
+               uh->check = csum_tcpudp_magic(ip_hdr(skb)->saddr,
+                                             ip_hdr(skb)->daddr,
+                                             udp_len, IPPROTO_UDP,
+                                             csum_partial(uh, udp_len, 0));
+               if (uh->check == 0)
+                       uh->check = CSUM_MANGLED_0;
+
+               csum_info->transmit.udp_checksum = 0;
        }
        goto do_send;
 
 
        ret = netvsc_send(net_device_ctx->device_ctx, packet);
 
+drop:
        if (ret == 0) {
                net->stats.tx_bytes += skb->len;
                net->stats.tx_packets++;
 
        struct rndis_set_complete *set_complete;
        u32 extlen = sizeof(struct ndis_offload_params);
        int ret, t;
+       u32 vsp_version = nvdev->nvsp_version;
+
+       if (vsp_version <= NVSP_PROTOCOL_VERSION_4) {
+               extlen = VERSION_4_OFFLOAD_SIZE;
+               /* On NVSP_PROTOCOL_VERSION_4 and below, we do not support
+                * UDP checksum offload.
+                */
+               req_offloads->udp_ip_v4_csum = 0;
+               req_offloads->udp_ip_v6_csum = 0;
+       }
 
        request = get_rndis_request(rdev, RNDIS_MSG_SET,
                RNDIS_MESSAGE_SIZE(struct rndis_set_request) + extlen);
        } else {
                set_complete = &request->response_msg.msg.set_complete;
                if (set_complete->status != RNDIS_STATUS_SUCCESS) {
-                       netdev_err(ndev, "Fail to set MAC on host side:0x%x\n",
+                       netdev_err(ndev, "Fail to set offload on host side:0x%x\n",
                                   set_complete->status);
                        ret = -EINVAL;
                }