diff options
author | Harout Hedeshian <harouth@codeaurora.org> | 2014-11-13 08:35:50 -0700 |
---|---|---|
committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-22 11:05:22 -0700 |
commit | 104da2c2579b47270c15acc606ed13b8a563292e (patch) | |
tree | 6f9179353c88af33f5f71373a169b54240202cb7 | |
parent | de93ca218074741c8718a6c40c3af866cd77a049 (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.c | 3 | ||||
-rw-r--r-- | net/rmnet_data/rmnet_map.h | 1 | ||||
-rw-r--r-- | net/rmnet_data/rmnet_map_data.c | 4 |
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, |