]> git.ipfire.org Git - ipfire-2.x.git/blame - src/patches/linux/0014-Drivers-net-hyperv-Address-UDP-checksum-issues.patch
make.sh limit build to 23 parallel threads.
[ipfire-2.x.git] / src / patches / linux / 0014-Drivers-net-hyperv-Address-UDP-checksum-issues.patch
CommitLineData
a7b0967d
MT
1From b822ee7a17efd1bc8c7584da5d0a2c042e9ca5b6 Mon Sep 17 00:00:00 2001
2From: KY Srinivasan <kys@microsoft.com>
3Date: Wed, 9 Apr 2014 15:00:47 -0700
4Subject: [PATCH 14/25] Drivers: net: hyperv: Address UDP checksum issues
5
6ws2008r2 does not support UDP checksum offload. Thus, we cannnot turn on
7UDP offload in the host. Also, on ws2012 and ws2012 r2, there appear to be
8an issue with UDP checksum offload.
9Fix this issue by computing the UDP checksum in the Hyper-V driver.
10
11Based on Dave Miller's comments, in this version, I have COWed the skb
12before modifying the UDP header (the checksum field).
13
14Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
15Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
16Signed-off-by: David S. Miller <davem@davemloft.net>
17---
18 drivers/net/hyperv/hyperv_net.h | 1 +
19 drivers/net/hyperv/netvsc_drv.c | 26 +++++++++++++++++++++++++-
20 drivers/net/hyperv/rndis_filter.c | 12 +++++++++++-
21 3 files changed, 37 insertions(+), 2 deletions(-)
22
23diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
24index 13010b4dae5b..d18f711d0b0c 100644
25--- a/drivers/net/hyperv/hyperv_net.h
26+++ b/drivers/net/hyperv/hyperv_net.h
27@@ -747,6 +747,7 @@ struct ndis_oject_header {
28 #define NDIS_TCP_LARGE_SEND_OFFLOAD_IPV4 0
29 #define NDIS_TCP_LARGE_SEND_OFFLOAD_IPV6 1
30
31+#define VERSION_4_OFFLOAD_SIZE 22
32 /*
33 * New offload OIDs for NDIS 6
34 */
35diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
36index c76c85176644..0d898876689e 100644
37--- a/drivers/net/hyperv/netvsc_drv.c
38+++ b/drivers/net/hyperv/netvsc_drv.c
39@@ -399,7 +399,30 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
40 csum_info->transmit.tcp_checksum = 1;
41 csum_info->transmit.tcp_header_offset = hdr_offset;
42 } else if (net_trans_info & INFO_UDP) {
43- csum_info->transmit.udp_checksum = 1;
44+ /* UDP checksum offload is not supported on ws2008r2.
45+ * Furthermore, on ws2012 and ws2012r2, there are some
46+ * issues with udp checksum offload from Linux guests.
47+ * (these are host issues).
48+ * For now compute the checksum here.
49+ */
50+ struct udphdr *uh;
51+ u16 udp_len;
52+
53+ ret = skb_cow_head(skb, 0);
54+ if (ret)
55+ goto drop;
56+
57+ uh = udp_hdr(skb);
58+ udp_len = ntohs(uh->len);
59+ uh->check = 0;
60+ uh->check = csum_tcpudp_magic(ip_hdr(skb)->saddr,
61+ ip_hdr(skb)->daddr,
62+ udp_len, IPPROTO_UDP,
63+ csum_partial(uh, udp_len, 0));
64+ if (uh->check == 0)
65+ uh->check = CSUM_MANGLED_0;
66+
67+ csum_info->transmit.udp_checksum = 0;
68 }
69 goto do_send;
70
71@@ -439,6 +462,7 @@ do_send:
72
73 ret = netvsc_send(net_device_ctx->device_ctx, packet);
74
75+drop:
76 if (ret == 0) {
77 net->stats.tx_bytes += skb_length;
78 net->stats.tx_packets++;
79diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
80index 4a37e3db9e32..143a98caf618 100644
81--- a/drivers/net/hyperv/rndis_filter.c
82+++ b/drivers/net/hyperv/rndis_filter.c
83@@ -641,6 +641,16 @@ int rndis_filter_set_offload_params(struct hv_device *hdev,
84 struct rndis_set_complete *set_complete;
85 u32 extlen = sizeof(struct ndis_offload_params);
86 int ret, t;
87+ u32 vsp_version = nvdev->nvsp_version;
88+
89+ if (vsp_version <= NVSP_PROTOCOL_VERSION_4) {
90+ extlen = VERSION_4_OFFLOAD_SIZE;
91+ /* On NVSP_PROTOCOL_VERSION_4 and below, we do not support
92+ * UDP checksum offload.
93+ */
94+ req_offloads->udp_ip_v4_csum = 0;
95+ req_offloads->udp_ip_v6_csum = 0;
96+ }
97
98 request = get_rndis_request(rdev, RNDIS_MSG_SET,
99 RNDIS_MESSAGE_SIZE(struct rndis_set_request) + extlen);
100@@ -674,7 +684,7 @@ int rndis_filter_set_offload_params(struct hv_device *hdev,
101 } else {
102 set_complete = &request->response_msg.msg.set_complete;
103 if (set_complete->status != RNDIS_STATUS_SUCCESS) {
104- netdev_err(ndev, "Fail to set MAC on host side:0x%x\n",
105+ netdev_err(ndev, "Fail to set offload on host side:0x%x\n",
106 set_complete->status);
107 ret = -EINVAL;
108 }
109--
1102.4.3
111