]> git.ipfire.org Git - ipfire-2.x.git/blame - src/patches/linux/0009-Drivers-net-hyperv-Enable-send-side-checksum-offload.patch
make.sh limit build to 23 parallel threads.
[ipfire-2.x.git] / src / patches / linux / 0009-Drivers-net-hyperv-Enable-send-side-checksum-offload.patch
CommitLineData
a7b0967d
MT
1From d2a0be7f4263eb669af84240c5424a72cce4cdb4 Mon Sep 17 00:00:00 2001
2From: KY Srinivasan <kys@microsoft.com>
3Date: Sat, 8 Mar 2014 19:23:17 -0800
4Subject: [PATCH 09/25] Drivers: net: hyperv: Enable send side checksum offload
5
6Enable send side checksum offload.
7
8Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
9Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
10Signed-off-by: David S. Miller <davem@davemloft.net>
11---
12 drivers/net/hyperv/hyperv_net.h | 10 ++++++
13 drivers/net/hyperv/netvsc_drv.c | 69 +++++++++++++++++++++++++++++++++++++++--
14 2 files changed, 77 insertions(+), 2 deletions(-)
15
16diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
17index faeb74623fbd..4cf238234321 100644
18--- a/drivers/net/hyperv/hyperv_net.h
19+++ b/drivers/net/hyperv/hyperv_net.h
20@@ -1035,6 +1035,16 @@ struct rndis_message {
21 #define NDIS_PACKET_TYPE_FUNCTIONAL 0x00000400
22 #define NDIS_PACKET_TYPE_MAC_FRAME 0x00000800
23
24+#define INFO_IPV4 2
25+#define INFO_IPV6 4
26+#define INFO_TCP 2
27+#define INFO_UDP 4
28+
29+#define TRANSPORT_INFO_NOT_IP 0
30+#define TRANSPORT_INFO_IPV4_TCP ((INFO_IPV4 << 16) | INFO_TCP)
31+#define TRANSPORT_INFO_IPV4_UDP ((INFO_IPV4 << 16) | INFO_UDP)
32+#define TRANSPORT_INFO_IPV6_TCP ((INFO_IPV6 << 16) | INFO_TCP)
33+#define TRANSPORT_INFO_IPV6_UDP ((INFO_IPV6 << 16) | INFO_UDP)
34
35
36 #endif /* _HYPERV_NET_H */
37diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
38index 7438360b7a02..2fab69ac61ef 100644
39--- a/drivers/net/hyperv/netvsc_drv.c
40+++ b/drivers/net/hyperv/netvsc_drv.c
41@@ -257,6 +257,35 @@ static int netvsc_get_slots(struct sk_buff *skb)
42 return slots + frag_slots;
43 }
44
45+static u32 get_net_transport_info(struct sk_buff *skb, u32 *trans_off)
46+{
47+ u32 ret_val = TRANSPORT_INFO_NOT_IP;
48+
49+ if ((eth_hdr(skb)->h_proto != htons(ETH_P_IP)) &&
50+ (eth_hdr(skb)->h_proto != htons(ETH_P_IPV6))) {
51+ goto not_ip;
52+ }
53+
54+ *trans_off = skb_transport_offset(skb);
55+
56+ if ((eth_hdr(skb)->h_proto == htons(ETH_P_IP))) {
57+ struct iphdr *iphdr = ip_hdr(skb);
58+
59+ if (iphdr->protocol == IPPROTO_TCP)
60+ ret_val = TRANSPORT_INFO_IPV4_TCP;
61+ else if (iphdr->protocol == IPPROTO_UDP)
62+ ret_val = TRANSPORT_INFO_IPV4_UDP;
63+ } else {
64+ if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP)
65+ ret_val = TRANSPORT_INFO_IPV6_TCP;
66+ else if (ipv6_hdr(skb)->nexthdr == IPPROTO_UDP)
67+ ret_val = TRANSPORT_INFO_IPV6_UDP;
68+ }
69+
70+not_ip:
71+ return ret_val;
72+}
73+
74 static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
75 {
76 struct net_device_context *net_device_ctx = netdev_priv(net);
77@@ -269,6 +298,10 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
78 u32 rndis_msg_size;
79 bool isvlan;
80 struct rndis_per_packet_info *ppi;
81+ struct ndis_tcp_ip_checksum_info *csum_info;
82+ int hdr_offset;
83+ u32 net_trans_info;
84+
85
86 /* We will atmost need two pages to describe the rndis
87 * header. We can only transmit MAX_PAGE_BUFFER_COUNT number
88@@ -336,6 +369,37 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
89 VLAN_PRIO_SHIFT;
90 }
91
92+ net_trans_info = get_net_transport_info(skb, &hdr_offset);
93+ if (net_trans_info == TRANSPORT_INFO_NOT_IP)
94+ goto do_send;
95+
96+ /*
97+ * Setup the sendside checksum offload only if this is not a
98+ * GSO packet.
99+ */
100+ if (skb_is_gso(skb))
101+ goto do_send;
102+
103+ rndis_msg_size += NDIS_CSUM_PPI_SIZE;
104+ ppi = init_ppi_data(rndis_msg, NDIS_CSUM_PPI_SIZE,
105+ TCPIP_CHKSUM_PKTINFO);
106+
107+ csum_info = (struct ndis_tcp_ip_checksum_info *)((void *)ppi +
108+ ppi->ppi_offset);
109+
110+ if (net_trans_info & (INFO_IPV4 << 16))
111+ csum_info->transmit.is_ipv4 = 1;
112+ else
113+ csum_info->transmit.is_ipv6 = 1;
114+
115+ if (net_trans_info & INFO_TCP) {
116+ csum_info->transmit.tcp_checksum = 1;
117+ csum_info->transmit.tcp_header_offset = hdr_offset;
118+ } else if (net_trans_info & INFO_UDP) {
119+ csum_info->transmit.udp_checksum = 1;
120+ }
121+
122+do_send:
123 /* Start filling in the page buffers with the rndis hdr */
124 rndis_msg->msg_len += rndis_msg_size;
125 packet->page_buf_cnt = init_page_array(rndis_msg, rndis_msg_size,
126@@ -592,8 +656,9 @@ static int netvsc_probe(struct hv_device *dev,
127 net->netdev_ops = &device_ops;
128
129 /* TODO: Add GSO and Checksum offload */
130- net->hw_features = NETIF_F_RXCSUM | NETIF_F_SG;
131- net->features = NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_SG | NETIF_F_RXCSUM;
132+ net->hw_features = NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_IP_CSUM;
133+ net->features = NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_SG | NETIF_F_RXCSUM |
134+ NETIF_F_IP_CSUM;
135
136 SET_ETHTOOL_OPS(net, &ethtool_ops);
137 SET_NETDEV_DEV(net, &dev->device);
138--
1392.4.3
140