]> git.ipfire.org Git - ipfire-2.x.git/blob - 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
1 From d2a0be7f4263eb669af84240c5424a72cce4cdb4 Mon Sep 17 00:00:00 2001
2 From: KY Srinivasan <kys@microsoft.com>
3 Date: Sat, 8 Mar 2014 19:23:17 -0800
4 Subject: [PATCH 09/25] Drivers: net: hyperv: Enable send side checksum offload
5
6 Enable send side checksum offload.
7
8 Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
9 Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
10 Signed-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
16 diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
17 index 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 */
37 diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
38 index 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 --
139 2.4.3
140