extern int sysctl_tcp_bic_fast_convergence;
extern int sysctl_tcp_bic_low_window;
extern int sysctl_tcp_moderate_rcvbuf;
+extern int sysctl_tcp_tso_win_divisor;
extern atomic_t tcp_memory_allocated;
extern atomic_t tcp_sockets_allocated;
.mode = 0644,
.proc_handler = &proc_dointvec,
},
+ {
+ .ctl_name = NET_TCP_TSO_WIN_DIVISOR,
+ .procname = "tcp_tso_win_divisor",
+ .data = &sysctl_tcp_tso_win_divisor,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
+ },
{ .ctl_name = 0 }
};
/* People can turn this off for buggy TCP's found in printers etc. */
int sysctl_tcp_retrans_collapse = 1;
+/* This limits the percentage of the congestion window which we
+ * will allow a single TSO frame to consume. Building TSO frames
+ * which are too large can cause TCP streams to be bursty.
+ */
+int sysctl_tcp_tso_win_divisor = 8;
+
static __inline__
void update_send_head(struct sock *sk, struct tcp_opt *tp, struct sk_buff *skb)
{
{
struct tcp_opt *tp = tcp_sk(sk);
struct dst_entry *dst = __sk_dst_get(sk);
- int do_large, mss_now;
+ unsigned int do_large, mss_now;
mss_now = tp->mss_cache_std;
if (dst) {
!tp->urg_mode);
if (do_large) {
- int large_mss, factor;
+ unsigned int large_mss, factor, limit;
large_mss = 65535 - tp->af_specific->net_header_len -
tp->ext_header_len - tp->ext2_header_len -
large_mss = max((tp->max_window>>1),
68U - tp->tcp_header_len);
+ factor = large_mss / mss_now;
+
/* Always keep large mss multiple of real mss, but
- * do not exceed 1/4 of the congestion window so we
- * can keep the ACK clock ticking.
+ * do not exceed 1/tso_win_divisor of the congestion window
+ * so we can keep the ACK clock ticking and minimize
+ * bursting.
*/
- factor = large_mss / mss_now;
- if (factor > (tp->snd_cwnd >> 2))
- factor = max(1, tp->snd_cwnd >> 2);
+ limit = tp->snd_cwnd;
+ if (sysctl_tcp_tso_win_divisor)
+ limit /= sysctl_tcp_tso_win_divisor;
+ limit = max(1U, limit);
+ if (factor > limit)
+ factor = limit;
tp->mss_cache = mss_now * factor;