diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/rmnet_data/rmnet_data_config.h | 3 | ||||
-rw-r--r-- | net/rmnet_data/rmnet_data_handlers.c | 35 |
2 files changed, 37 insertions, 1 deletions
diff --git a/net/rmnet_data/rmnet_data_config.h b/net/rmnet_data/rmnet_data_config.h index fe668a86eb45..a76bcef79e6a 100644 --- a/net/rmnet_data/rmnet_data_config.h +++ b/net/rmnet_data/rmnet_data_config.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2014, 2016 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 @@ -38,6 +38,7 @@ struct rmnet_logical_ep_conf_s { uint8_t refcount; uint8_t rmnet_mode; uint8_t mux_id; + struct timespec flush_time; struct net_device *egress_dev; }; diff --git a/net/rmnet_data/rmnet_data_handlers.c b/net/rmnet_data/rmnet_data_handlers.c index 8b3ed2cdffbf..7ea599f746c2 100644 --- a/net/rmnet_data/rmnet_data_handlers.c +++ b/net/rmnet_data/rmnet_data_handlers.c @@ -45,6 +45,11 @@ module_param(dump_pkt_tx, uint, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(dump_pkt_tx, "Dump packets exiting egress handler"); #endif /* CONFIG_RMNET_DATA_DEBUG_PKT */ +/* Time in nano seconds. This number must be less that a second. */ +long gro_flush_time __read_mostly = 10000L; +module_param(gro_flush_time, long, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(gro_flush_time, "Flush GRO when spaced more than this"); + #define RMNET_DATA_IP_VERSION_4 0x40 #define RMNET_DATA_IP_VERSION_6 0x60 @@ -217,6 +222,35 @@ static int rmnet_check_skb_can_gro(struct sk_buff *skb) } /** + * rmnet_optional_gro_flush() - Check if GRO handler needs to flush now + * + * Determines whether GRO handler needs to flush packets which it has + * coalesced so far. + * + * Tuning this parameter will trade TCP slow start performance for GRO coalesce + * ratio. + */ +static void rmnet_optional_gro_flush(struct napi_struct *napi, + struct rmnet_logical_ep_conf_s *ep) +{ + struct timespec curr_time, diff; + + if (!gro_flush_time) + return; + + if (unlikely(ep->flush_time.tv_sec == 0)) { + getnstimeofday(&ep->flush_time); + } else { + getnstimeofday(&(curr_time)); + diff = timespec_sub(curr_time, ep->flush_time); + if ((diff.tv_sec > 0) || (diff.tv_nsec > gro_flush_time)) { + napi_gro_flush(napi, false); + getnstimeofday(&ep->flush_time); + } + } +} + +/** * __rmnet_deliver_skb() - Deliver skb * * Determines where to deliver skb. Options are: consume by network stack, @@ -256,6 +290,7 @@ static rx_handler_result_t __rmnet_deliver_skb(struct sk_buff *skb, if (napi != NULL) { gro_res = napi_gro_receive(napi, skb); trace_rmnet_gro_downlink(gro_res); + rmnet_optional_gro_flush(napi, ep); } else { WARN_ONCE(1, "current napi is NULL\n"); netif_receive_skb(skb); |