mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-16 15:34:48 +08:00
Merge branch 'hyperv'
K. Y. Srinivasan says: ==================== Fix issues with Heper-V network offload code WS2008 R2 does not support udp checksum offload. Furthermore, ws2012 and ws2012 r2 have issues offloading udp checksum from Linux guests. This patch-set addresses these issues as well as other bug fixes. Please apply. In this version, I have addressed the comment from David Miller with reagards to COWing the skb prior to modifying the header (patch 3/3). ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
ad20d5f673
@ -747,6 +747,7 @@ struct ndis_oject_header {
|
||||
#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
|
||||
*/
|
||||
|
@ -344,7 +344,7 @@ static int netvsc_connect_vsp(struct hv_device *device)
|
||||
memset(init_packet, 0, sizeof(struct nvsp_message));
|
||||
|
||||
if (net_device->nvsp_version <= NVSP_PROTOCOL_VERSION_4)
|
||||
ndis_version = 0x00050001;
|
||||
ndis_version = 0x00060001;
|
||||
else
|
||||
ndis_version = 0x0006001e;
|
||||
|
||||
|
@ -319,7 +319,9 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
|
||||
packet = kzalloc(sizeof(struct hv_netvsc_packet) +
|
||||
(num_data_pgs * sizeof(struct hv_page_buffer)) +
|
||||
sizeof(struct rndis_message) +
|
||||
NDIS_VLAN_PPI_SIZE, GFP_ATOMIC);
|
||||
NDIS_VLAN_PPI_SIZE +
|
||||
NDIS_CSUM_PPI_SIZE +
|
||||
NDIS_LSO_PPI_SIZE, GFP_ATOMIC);
|
||||
if (!packet) {
|
||||
/* out of memory, drop packet */
|
||||
netdev_err(net, "unable to allocate hv_netvsc_packet\n");
|
||||
@ -396,7 +398,30 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
|
||||
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;
|
||||
|
||||
@ -436,6 +461,7 @@ 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++;
|
||||
|
@ -641,6 +641,16 @@ int rndis_filter_set_offload_params(struct hv_device *hdev,
|
||||
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);
|
||||
@ -674,7 +684,7 @@ int rndis_filter_set_offload_params(struct hv_device *hdev,
|
||||
} 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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user