@@ -385,7 +385,8 @@ struct tcp_sock {
syn_fastopen:1, /* SYN includes Fast Open option */
syn_fastopen_exp:1,/* SYN includes Fast Open exp. option */
syn_fastopen_ch:1, /* Active TFO re-enabling probe */
- syn_data_acked:1;/* data in SYN is acked by SYN-ACK */
+ syn_data_acked:1,/* data in SYN is acked by SYN-ACK */
+ dynamic_initcwnd:1; /* dynamic adjustment for initcwnd */
u8 keepalive_probes; /* num of allowed keep alive probes */
u32 tcp_tx_delay; /* delay (in usec) added to TX packets */
@@ -143,6 +143,7 @@ enum {
#define TCP_RTO_MIN_US 45 /* min rto time in us */
#define TCP_DELACK_MAX_US 46 /* max delayed ack time in us */
#define TCP_IW 47 /* initial congestion window */
+#define TCP_IW_DYNAMIC 48 /* dynamic adjustment for initcwnd */
#define TCP_REPAIR_ON 1
#define TCP_REPAIR_OFF 0
@@ -3868,6 +3868,11 @@ int do_tcp_setsockopt(struct sock *sk, int level, int optname,
return -EINVAL;
tp->init_cwnd = val;
return 0;
+ case TCP_IW_DYNAMIC:
+ if (val < 0 || val > 1)
+ return -EINVAL;
+ tp->dynamic_initcwnd = val;
+ return 0;
}
sockopt_lock_sock(sk);
@@ -4716,6 +4721,9 @@ int do_tcp_getsockopt(struct sock *sk, int level,
case TCP_IW:
val = tp->init_cwnd;
break;
+ case TCP_IW_DYNAMIC:
+ val = tp->dynamic_initcwnd;
+ break;
default:
return -ENOPROTOOPT;
}
@@ -6341,10 +6341,17 @@ void tcp_init_transfer(struct sock *sk, int bpf_op, struct sk_buff *skb)
* initRTO, we only reset cwnd when more than 1 SYN/SYN-ACK
* retransmission has occurred.
*/
- if (tp->total_retrans > 1 && tp->undo_marker)
+ if (tp->total_retrans > 1 && tp->undo_marker) {
tcp_snd_cwnd_set(tp, 1);
- else
+ } else {
+ if (tp->dynamic_initcwnd) {
+ u32 win = min(tp->max_window, 65535);
+
+ tp->init_cwnd = max(win / tp->mss_cache, TCP_INIT_CWND);
+ }
+
tcp_snd_cwnd_set(tp, tcp_init_cwnd(tp, __sk_dst_get(sk)));
+ }
tp->snd_cwnd_stamp = tcp_jiffies32;
bpf_skops_established(sk, bpf_op, skb);