net: rmnet_data: Fix incorrect UL checksum offload logic
The udp_ip4_ind bit is set only for IPv4 UDP non-fragmented packets so that the hardware can flip the checksum to 0xFFFF if the computed checksum is 0 per RFC768. However, this bit had to be set for IPv6 UDP non fragmented packets as well per hardware requirements. Otherwise, IPv6 UDP packets with computed checksum as 0 were transmitted by hardware and were dropped in the network. In addition to setting this bit for IPv6 UDP, the field is also appropriately renamed to udp_ind as part of this change. Change-Id: Ia00e3f364e9732b182b7aebe843beb443269fd9e Signed-off-by: Chinmay Agarwal <chinagar@codeaurora.org>
This commit is contained in:
parent
8e3a8759bd
commit
6ee188aa79
2 changed files with 13 additions and 8 deletions
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2013-2017, 2020 The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
|
|
@ -64,11 +64,11 @@ struct rmnet_map_ul_checksum_header_s {
|
|||
unsigned short checksum_start_offset;
|
||||
#if defined(__LITTLE_ENDIAN_BITFIELD)
|
||||
unsigned short checksum_insert_offset:14;
|
||||
unsigned short udp_ip4_ind:1;
|
||||
unsigned short udp_ind:1;
|
||||
unsigned short cks_en:1;
|
||||
#elif defined(__BIG_ENDIAN_BITFIELD)
|
||||
unsigned short cks_en:1;
|
||||
unsigned short udp_ip4_ind:1;
|
||||
unsigned short udp_ind:1;
|
||||
unsigned short checksum_insert_offset:14;
|
||||
#else
|
||||
#error "Please fix <asm/byteorder.h>"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2013-2020 The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
|
|
@ -625,9 +625,9 @@ static void rmnet_map_fill_ipv4_packet_ul_checksum_header
|
|||
ul_header->checksum_insert_offset = skb->csum_offset;
|
||||
ul_header->cks_en = 1;
|
||||
if (ip4h->protocol == IPPROTO_UDP)
|
||||
ul_header->udp_ip4_ind = 1;
|
||||
ul_header->udp_ind = 1;
|
||||
else
|
||||
ul_header->udp_ip4_ind = 0;
|
||||
ul_header->udp_ind = 0;
|
||||
/* Changing checksum_insert_offset to network order */
|
||||
hdr++;
|
||||
*hdr = htons(*hdr);
|
||||
|
|
@ -638,13 +638,18 @@ static void rmnet_map_fill_ipv6_packet_ul_checksum_header
|
|||
(void *iphdr, struct rmnet_map_ul_checksum_header_s *ul_header,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct ipv6hdr *ip6h = (struct ipv6hdr *)iphdr;
|
||||
unsigned short *hdr = (unsigned short *)ul_header;
|
||||
|
||||
ul_header->checksum_start_offset = htons((unsigned short)
|
||||
(skb_transport_header(skb) - (unsigned char *)iphdr));
|
||||
ul_header->checksum_insert_offset = skb->csum_offset;
|
||||
ul_header->cks_en = 1;
|
||||
ul_header->udp_ip4_ind = 0;
|
||||
|
||||
if (ip6h->nexthdr == IPPROTO_UDP)
|
||||
ul_header->udp_ind = 1;
|
||||
else
|
||||
ul_header->udp_ind = 0;
|
||||
/* Changing checksum_insert_offset to network order */
|
||||
hdr++;
|
||||
*hdr = htons(*hdr);
|
||||
|
|
@ -747,7 +752,7 @@ sw_checksum:
|
|||
ul_header->checksum_start_offset = 0;
|
||||
ul_header->checksum_insert_offset = 0;
|
||||
ul_header->cks_en = 0;
|
||||
ul_header->udp_ip4_ind = 0;
|
||||
ul_header->udp_ind = 0;
|
||||
done:
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue