net: rmnet_data: Skip UL aggregation for ping packets

ICMP packets could be potentially stuck behind aggregated traffic
if UL aggregation is enabled on rmnet_data. This results in
increased latencies during ping tests as the workqueues for these
packets are scheduled at non deterministic times.

CRs-Fixed: 2131879
Change-Id: I19208301b5674749aa2f1dee65a9226eda364c85
Signed-off-by: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
This commit is contained in:
Subash Abhinov Kasiviswanathan 2017-11-08 15:55:29 -07:00
commit bf783bade0
3 changed files with 35 additions and 10 deletions

View file

@ -597,6 +597,9 @@ static int rmnet_map_egress_handler(struct sk_buff *skb,
if ((config->egress_data_format & RMNET_EGRESS_FORMAT_AGGREGATION) &&
!non_linear_skb) {
if (rmnet_ul_aggregation_skip(skb, required_headroom))
return RMNET_MAP_SUCCESS;
rmnet_map_aggregate(skb, config);
return RMNET_MAP_CONSUMED;
}

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
/* Copyright (c) 2013-2017, 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
@ -146,5 +146,5 @@ int rmnet_map_checksum_downlink_packet(struct sk_buff *skb);
int rmnet_map_checksum_uplink_packet(struct sk_buff *skb,
struct net_device *orig_dev,
u32 egress_data_format);
int rmnet_ul_aggregation_skip(struct sk_buff *skb, int offset);
#endif /* _RMNET_MAP_H_ */

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
/* Copyright (c) 2013-2017, 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
@ -234,16 +234,9 @@ void rmnet_map_aggregate(struct sk_buff *skb,
if (!skb || !config)
return;
size = config->egress_agg_size - skb->len;
if (size < 2000) {
LOGL("Invalid length %d", size);
return;
}
new_packet:
spin_lock_irqsave(&config->agg_lock, flags);
memcpy(&last, &config->agg_last, sizeof(struct timespec));
getnstimeofday(&config->agg_last);
@ -265,6 +258,7 @@ new_packet:
return;
}
size = config->egress_agg_size - skb->len;
config->agg_skb = skb_copy_expand(skb, 0, size, GFP_ATOMIC);
if (!config->agg_skb) {
config->agg_skb = 0;
@ -748,3 +742,31 @@ sw_checksum:
done:
return ret;
}
int rmnet_ul_aggregation_skip(struct sk_buff *skb, int offset)
{
unsigned char *packet_start = skb->data + offset;
int is_icmp = 0;
if ((skb->data[offset]) >> 4 == 0x04) {
struct iphdr *ip4h = (struct iphdr *)(packet_start);
if (ip4h->protocol == IPPROTO_ICMP)
is_icmp = 1;
} else {
struct ipv6hdr *ip6h = (struct ipv6hdr *)(packet_start);
if (ip6h->nexthdr == NEXTHDR_FRAGMENT) {
struct frag_hdr *frag;
frag = (struct frag_hdr *)(packet_start
+ sizeof(struct ipv6hdr));
if (frag->nexthdr == IPPROTO_ICMPV6)
is_icmp = 1;
} else if (ip6h->nexthdr == IPPROTO_ICMPV6) {
is_icmp = 1;
}
}
return is_icmp;
}