summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHarout Hedeshian <harouth@codeaurora.org>2014-12-17 10:22:36 -0700
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-22 11:05:25 -0700
commit6ec986478d6bb9a960a119ea106cdaf04cebfb80 (patch)
treeb453d48994fd2bfcbb1198651a177fd12fc4e7a9
parent8fcebfae02c88e69ec1a43d3f67a16329d740d32 (diff)
net: rmnet_data: Further optimize UL aggregation accumulation
Do not aggregate frames if they are sapced out more than 10ms. Since the scedule_delayed_work() API only takes time in jiffies, ping packets are getting substantially delayed. Instead, just send them. This parameter is tunable from the module parameters location. CRs-Fixed: 772705 Change-Id: I6ac337c8d61b1290f939b86081070c14c2c757b1 Signed-off-by: Harout Hedeshian <harouth@codeaurora.org>
-rw-r--r--net/rmnet_data/rmnet_data_config.h8
-rw-r--r--net/rmnet_data/rmnet_data_stats.h1
-rw-r--r--net/rmnet_data/rmnet_map_data.c30
3 files changed, 35 insertions, 4 deletions
diff --git a/net/rmnet_data/rmnet_data_config.h b/net/rmnet_data/rmnet_data_config.h
index 6bacad45980e..fe668a86eb45 100644
--- a/net/rmnet_data/rmnet_data_config.h
+++ b/net/rmnet_data/rmnet_data_config.h
@@ -59,6 +59,7 @@ struct rmnet_logical_ep_conf_s {
* aggregation
* @tail_spacing: Guaranteed padding (bytes) when de-aggregating ingress frames
* @agg_time: Wall clock time when aggregated frame was created
+ * @agg_last: Last time the aggregation routing was invoked
*/
struct rmnet_phys_ep_conf_s {
struct net_device *dev;
@@ -70,12 +71,17 @@ struct rmnet_phys_ep_conf_s {
/* MAP specific */
uint16_t egress_agg_size;
uint16_t egress_agg_count;
+ uint8_t tail_spacing;
+ /* MAP aggregation state machine
+ * - This is not sctrictly configuration and is updated at runtime
+ * Make sure all of these are protected by the agg_lock
+ */
spinlock_t agg_lock;
struct sk_buff *agg_skb;
uint8_t agg_state;
uint8_t agg_count;
- uint8_t tail_spacing;
struct timespec agg_time;
+ struct timespec agg_last;
};
int rmnet_config_init(void);
diff --git a/net/rmnet_data/rmnet_data_stats.h b/net/rmnet_data/rmnet_data_stats.h
index e9b2f6c050e9..d5924f1e0768 100644
--- a/net/rmnet_data/rmnet_data_stats.h
+++ b/net/rmnet_data/rmnet_data_stats.h
@@ -48,6 +48,7 @@ enum rmnet_queue_xmit_e {
RMNET_STATS_QUEUE_XMIT_AGG_FILL_BUFFER,
RMNET_STATS_QUEUE_XMIT_AGG_TIMEOUT,
RMNET_STATS_QUEUE_XMIT_AGG_CPY_EXP_FAIL,
+ RMNET_STATS_QUEUE_XMIT_AGG_SKIP,
RMNET_STATS_QUEUE_XMIT_MAX
};
diff --git a/net/rmnet_data/rmnet_map_data.c b/net/rmnet_data/rmnet_map_data.c
index 3b3bc20dda87..4691ee5ed805 100644
--- a/net/rmnet_data/rmnet_map_data.c
+++ b/net/rmnet_data/rmnet_map_data.c
@@ -45,6 +45,10 @@ 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");
+long agg_bypass_time __read_mostly = 10000000L;
+module_param(agg_bypass_time, long, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(agg_bypass_time, "Skip agg when apart spaced more than this");
+
struct agg_work {
struct delayed_work work;
@@ -225,7 +229,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;
+ struct timespec diff, last;
int size, rc, agg_count = 0;
@@ -240,7 +244,28 @@ void rmnet_map_aggregate(struct sk_buff *skb,
new_packet:
spin_lock_irqsave(&config->agg_lock, flags);
+
+ memcpy(&last, &(config->agg_last), sizeof(struct timespec));
+ getnstimeofday(&(config->agg_last));
+
if (!config->agg_skb) {
+ /* Check to see if we should agg first. If the traffic is very
+ * sparse, don't aggregate. We will need to tune this later
+ */
+ diff = timespec_sub(config->agg_last, last);
+
+ if ((diff.tv_sec > 0) || (diff.tv_nsec > agg_bypass_time)) {
+ spin_unlock_irqrestore(&config->agg_lock, flags);
+ LOGL("delta t: %ld.%09lu\tcount: bypass", diff.tv_sec,
+ diff.tv_nsec);
+ rmnet_stats_agg_pkts(1);
+ trace_rmnet_map_aggregate(skb, 0);
+ rc = dev_queue_xmit(skb);
+ rmnet_stats_queue_xmit(rc,
+ RMNET_STATS_QUEUE_XMIT_AGG_SKIP);
+ return;
+ }
+
config->agg_skb = skb_copy_expand(skb, 0, size, GFP_ATOMIC);
if (!config->agg_skb) {
config->agg_skb = 0;
@@ -260,8 +285,7 @@ new_packet:
rmnet_kfree_skb(skb, RMNET_STATS_SKBFREE_AGG_CPY_EXPAND);
goto schedule;
}
- getnstimeofday(&t);
- diff = timespec_sub(t, config->agg_time);
+ diff = timespec_sub(config->agg_last, config->agg_time);
if (skb->len > (config->egress_agg_size - config->agg_skb->len)
|| (config->agg_count >= config->egress_agg_count)