summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHarout Hedeshian <harouth@codeaurora.org>2014-11-13 08:35:50 -0700
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-22 11:05:22 -0700
commit104da2c2579b47270c15acc606ed13b8a563292e (patch)
tree6f9179353c88af33f5f71373a169b54240202cb7
parentde93ca218074741c8718a6c40c3af866cd77a049 (diff)
net: rmnet_data: Checksum offload handle IPv4 UDP frames with 0 checksum
Checksum offload routine should skip checksum fixup computation on IPv4 UDP packets which have the checksum field set to 0 by the sender. This is allowed by RFC768. Packets are marked as checksum unnecessary and shipped up the stack as-is. CRs-Fixed: 755544 Change-Id: I0432c3e1b25196134ecc8bbbe23c9cab46666d5c Signed-off-by: Harout Hedeshian <harouth@codeaurora.org>
-rw-r--r--net/rmnet_data/rmnet_data_handlers.c3
-rw-r--r--net/rmnet_data/rmnet_map.h1
-rw-r--r--net/rmnet_data/rmnet_map_data.c4
3 files changed, 7 insertions, 1 deletions
diff --git a/net/rmnet_data/rmnet_data_handlers.c b/net/rmnet_data/rmnet_data_handlers.c
index ed25dc508ba4..b131cb1134f2 100644
--- a/net/rmnet_data/rmnet_data_handlers.c
+++ b/net/rmnet_data/rmnet_data_handlers.c
@@ -286,7 +286,8 @@ static rx_handler_result_t _rmnet_map_ingress_handler(struct sk_buff *skb,
ckresult = rmnet_map_checksum_downlink_packet(skb);
trace_rmnet_map_checksum_downlink_packet(skb, ckresult);
rmnet_stats_dl_checksum(ckresult);
- if (likely(ckresult == RMNET_MAP_CHECKSUM_OK))
+ if (likely((ckresult == RMNET_MAP_CHECKSUM_OK)
+ || (ckresult == RMNET_MAP_CHECKSUM_SKIPPED)))
skb->ip_summed |= CHECKSUM_UNNECESSARY;
else if (ckresult != RMNET_MAP_CHECKSUM_ERR_UNKNOWN_IP_VERSION
&& ckresult != RMNET_MAP_CHECKSUM_ERR_UNKNOWN_TRANSPORT
diff --git a/net/rmnet_data/rmnet_map.h b/net/rmnet_data/rmnet_map.h
index c219b43f425c..f6d253609695 100644
--- a/net/rmnet_data/rmnet_map.h
+++ b/net/rmnet_data/rmnet_map.h
@@ -88,6 +88,7 @@ enum rmnet_map_checksum_errors_e {
RMNET_MAP_CHECKSUM_ERR_UNKNOWN_IP_VERSION,
RMNET_MAP_CHECKSUM_ERR_UNKNOWN_TRANSPORT,
RMNET_MAP_CHECKSUM_FRAGMENTED_PACKET,
+ RMNET_MAP_CHECKSUM_SKIPPED,
/* This should always be the last element */
RMNET_MAP_CHECKSUM_ENUM_LENGTH
};
diff --git a/net/rmnet_data/rmnet_map_data.c b/net/rmnet_data/rmnet_map_data.c
index 24db006c7591..96ce624e5df0 100644
--- a/net/rmnet_data/rmnet_map_data.c
+++ b/net/rmnet_data/rmnet_map_data.c
@@ -377,6 +377,10 @@ static int rmnet_map_validate_ipv4_packet_checksum(unsigned char *map_payload,
if (unlikely(!checksum_field))
return RMNET_MAP_CHECKSUM_ERR_UNKNOWN_TRANSPORT;
+ /* RFC 768 - Skip IPv4 UDP packets where sender checksum field is 0 */
+ if ((*checksum_field == 0) && (ip4h->protocol == IPPROTO_UDP))
+ return RMNET_MAP_CHECKSUM_SKIPPED;
+
checksum_value = ~ntohs(cksum_trailer->checksum_value);
ip_hdr_checksum = ~ip_fast_csum(ip4h, (int)ip4h->ihl);
ip_payload_checksum = rmnet_map_subtract_checksums(checksum_value,