net: rmnet_data: Optimize UL aggregation accumulation logic

Accumulation logic now respects max packet count as well as buffer size.
Additionally, packets will get shipped if they have been sitting around
for more than 1ms. This parameter is tunable from the module parameters
location.

CRs-Fixed: 772705
Change-Id: I1b5cb597ef6adfe19df590582f9a6cae091c5977
Signed-off-by: Harout Hedeshian <harouth@codeaurora.org>
This commit is contained in:
Harout Hedeshian 2014-12-17 09:34:36 -07:00 committed by David Keitel
parent af786e544f
commit 8fcebfae02
2 changed files with 23 additions and 3 deletions

View file

@ -15,6 +15,7 @@
*/
#include <linux/types.h>
#include <linux/time.h>
#include <linux/spinlock.h>
#ifndef _RMNET_DATA_CONFIG_H_
@ -57,6 +58,7 @@ struct rmnet_logical_ep_conf_s {
* Smaller of the two parameters above are chosen for
* aggregation
* @tail_spacing: Guaranteed padding (bytes) when de-aggregating ingress frames
* @agg_time: Wall clock time when aggregated frame was created
*/
struct rmnet_phys_ep_conf_s {
struct net_device *dev;
@ -73,6 +75,7 @@ struct rmnet_phys_ep_conf_s {
uint8_t agg_state;
uint8_t agg_count;
uint8_t tail_spacing;
struct timespec agg_time;
};
int rmnet_config_init(void);

View file

@ -21,6 +21,7 @@
#include <linux/rmnet_data.h>
#include <linux/spinlock.h>
#include <linux/workqueue.h>
#include <linux/time.h>
#include <linux/net_map.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
@ -39,6 +40,12 @@
RMNET_LOG_MODULE(RMNET_DATA_LOGMASK_MAPD);
/* ***************** Local Definitions ************************************** */
long agg_time_limit __read_mostly = 1000000L;
module_param(agg_time_limit, long, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(agg_time_limit, "Maximum time packets sit in the agg buf");
struct agg_work {
struct delayed_work work;
struct rmnet_phys_ep_conf_s *config;
@ -184,6 +191,8 @@ static void rmnet_map_flush_packet_queue(struct work_struct *work)
skb = config->agg_skb;
agg_count = config->agg_count;
config->agg_skb = 0;
config->agg_count = 0;
memset(&(config->agg_time), 0, sizeof(struct timespec));
}
config->agg_state = RMNET_MAP_AGG_IDLE;
} else {
@ -216,6 +225,7 @@ void rmnet_map_aggregate(struct sk_buff *skb,
struct agg_work *work;
unsigned long flags;
struct sk_buff *agg_skb;
struct timespec t, diff;
int size, rc, agg_count = 0;
@ -235,6 +245,7 @@ new_packet:
if (!config->agg_skb) {
config->agg_skb = 0;
config->agg_count = 0;
memset(&(config->agg_time), 0, sizeof(struct timespec));
spin_unlock_irqrestore(&config->agg_lock, flags);
rmnet_stats_agg_pkts(1);
trace_rmnet_map_aggregate(skb, 0);
@ -244,20 +255,26 @@ new_packet:
return;
}
config->agg_count = 1;
getnstimeofday(&(config->agg_time));
trace_rmnet_start_aggregation(skb);
rmnet_kfree_skb(skb, RMNET_STATS_SKBFREE_AGG_CPY_EXPAND);
goto schedule;
}
getnstimeofday(&t);
diff = timespec_sub(t, config->agg_time);
if (skb->len > (config->egress_agg_size - config->agg_skb->len)) {
if (skb->len > (config->egress_agg_size - config->agg_skb->len)
|| (config->agg_count >= config->egress_agg_count)
|| (diff.tv_sec > 0) || (diff.tv_nsec > agg_time_limit)) {
rmnet_stats_agg_pkts(config->agg_count);
if (config->agg_count > 1)
LOGL("Agg count: %d", config->agg_count);
agg_skb = config->agg_skb;
agg_count = config->agg_count;
config->agg_skb = 0;
config->agg_count = 0;
memset(&(config->agg_time), 0, sizeof(struct timespec));
spin_unlock_irqrestore(&config->agg_lock, flags);
LOGL("delta t: %ld.%09lu\tcount: %d", diff.tv_sec,
diff.tv_nsec, agg_count);
trace_rmnet_map_aggregate(skb, agg_count);
rc = dev_queue_xmit(agg_skb);
rmnet_stats_queue_xmit(rc,