]> git.ipfire.org Git - ipfire-2.x.git/blob - 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
1 From b822ee7a17efd1bc8c7584da5d0a2c042e9ca5b6 Mon Sep 17 00:00:00 2001
2 From: KY Srinivasan <kys@microsoft.com>
3 Date: Wed, 9 Apr 2014 15:00:47 -0700
4 Subject: [PATCH 14/25] Drivers: net: hyperv: Address UDP checksum issues
5
6 ws2008r2 does not support UDP checksum offload. Thus, we cannnot turn on
7 UDP offload in the host. Also, on ws2012 and ws2012 r2, there appear to be
8 an issue with UDP checksum offload.
9 Fix this issue by computing the UDP checksum in the Hyper-V driver.
10
11 Based on Dave Miller's comments, in this version, I have COWed the skb
12 before modifying the UDP header (the checksum field).
13
14 Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
15 Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
16 Signed-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
23 diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
24 index 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 */
35 diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
36 index 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++;
79 diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
80 index 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 --
110 2.4.3
111