浏览代码

net: Add rtnetlink init_rcvwnd to set the TCP initial receive window

Add rtnetlink init_rcvwnd to set the TCP initial receive window size
advertised by passive and active TCP connections.
The current Linux TCP implementation limits the advertised TCP initial
receive window to the one prescribed by slow start. For short lived
TCP connections used for transaction type of traffic (i.e. http
requests), bounding the advertised TCP initial receive window results
in increased latency to complete the transaction.
Support for setting initial congestion window is already supported
using rtnetlink init_cwnd, but the feature is useless without the
ability to set a larger TCP initial receive window.
The rtnetlink init_rcvwnd allows increasing the TCP initial receive
window, allowing TCP connection to advertise larger TCP receive window
than the ones bounded by slow start.

Signed-off-by: Laurent Chavey <chavey@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
laurent chavey 15 年之前
父节点
当前提交
31d12926e3
共有 6 个文件被更改,包括 21 次插入9 次删除
  1. 2 0
      include/linux/rtnetlink.h
  2. 0 2
      include/net/dst.h
  3. 2 1
      include/net/tcp.h
  4. 2 1
      net/ipv4/syncookies.c
  5. 13 4
      net/ipv4/tcp_output.c
  6. 2 1
      net/ipv6/syncookies.c

+ 2 - 0
include/linux/rtnetlink.h

@@ -362,6 +362,8 @@ enum {
 #define RTAX_FEATURES RTAX_FEATURES
 #define RTAX_FEATURES RTAX_FEATURES
 	RTAX_RTO_MIN,
 	RTAX_RTO_MIN,
 #define RTAX_RTO_MIN RTAX_RTO_MIN
 #define RTAX_RTO_MIN RTAX_RTO_MIN
+	RTAX_INITRWND,
+#define RTAX_INITRWND RTAX_INITRWND
 	__RTAX_MAX
 	__RTAX_MAX
 };
 };
 
 

+ 0 - 2
include/net/dst.h

@@ -83,8 +83,6 @@ struct dst_entry {
 	 * (L1_CACHE_SIZE would be too much)
 	 * (L1_CACHE_SIZE would be too much)
 	 */
 	 */
 #ifdef CONFIG_64BIT
 #ifdef CONFIG_64BIT
-	long			__pad_to_align_refcnt[2];
-#else
 	long			__pad_to_align_refcnt[1];
 	long			__pad_to_align_refcnt[1];
 #endif
 #endif
 	/*
 	/*

+ 2 - 1
include/net/tcp.h

@@ -965,7 +965,8 @@ static inline void tcp_sack_reset(struct tcp_options_received *rx_opt)
 /* Determine a window scaling and initial window to offer. */
 /* Determine a window scaling and initial window to offer. */
 extern void tcp_select_initial_window(int __space, __u32 mss,
 extern void tcp_select_initial_window(int __space, __u32 mss,
 				      __u32 *rcv_wnd, __u32 *window_clamp,
 				      __u32 *rcv_wnd, __u32 *window_clamp,
-				      int wscale_ok, __u8 *rcv_wscale);
+				      int wscale_ok, __u8 *rcv_wscale,
+				      __u32 init_rcv_wnd);
 
 
 static inline int tcp_win_from_space(int space)
 static inline int tcp_win_from_space(int space)
 {
 {

+ 2 - 1
net/ipv4/syncookies.c

@@ -358,7 +358,8 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
 
 
 	tcp_select_initial_window(tcp_full_space(sk), req->mss,
 	tcp_select_initial_window(tcp_full_space(sk), req->mss,
 				  &req->rcv_wnd, &req->window_clamp,
 				  &req->rcv_wnd, &req->window_clamp,
-				  ireq->wscale_ok, &rcv_wscale);
+				  ireq->wscale_ok, &rcv_wscale,
+				  dst_metric(&rt->u.dst, RTAX_INITRWND));
 
 
 	ireq->rcv_wscale  = rcv_wscale;
 	ireq->rcv_wscale  = rcv_wscale;
 
 

+ 13 - 4
net/ipv4/tcp_output.c

@@ -183,7 +183,8 @@ static inline void tcp_event_ack_sent(struct sock *sk, unsigned int pkts)
  */
  */
 void tcp_select_initial_window(int __space, __u32 mss,
 void tcp_select_initial_window(int __space, __u32 mss,
 			       __u32 *rcv_wnd, __u32 *window_clamp,
 			       __u32 *rcv_wnd, __u32 *window_clamp,
-			       int wscale_ok, __u8 *rcv_wscale)
+			       int wscale_ok, __u8 *rcv_wscale,
+			       __u32 init_rcv_wnd)
 {
 {
 	unsigned int space = (__space < 0 ? 0 : __space);
 	unsigned int space = (__space < 0 ? 0 : __space);
 
 
@@ -232,7 +233,13 @@ void tcp_select_initial_window(int __space, __u32 mss,
 			init_cwnd = 2;
 			init_cwnd = 2;
 		else if (mss > 1460)
 		else if (mss > 1460)
 			init_cwnd = 3;
 			init_cwnd = 3;
-		if (*rcv_wnd > init_cwnd * mss)
+		/* when initializing use the value from init_rcv_wnd
+		 * rather than the default from above
+		 */
+		if (init_rcv_wnd &&
+		    (*rcv_wnd > init_rcv_wnd * mss))
+			*rcv_wnd = init_rcv_wnd * mss;
+		else if (*rcv_wnd > init_cwnd * mss)
 			*rcv_wnd = init_cwnd * mss;
 			*rcv_wnd = init_cwnd * mss;
 	}
 	}
 
 
@@ -2417,7 +2424,8 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
 			&req->rcv_wnd,
 			&req->rcv_wnd,
 			&req->window_clamp,
 			&req->window_clamp,
 			ireq->wscale_ok,
 			ireq->wscale_ok,
-			&rcv_wscale);
+			&rcv_wscale,
+			dst_metric(dst, RTAX_INITRWND));
 		ireq->rcv_wscale = rcv_wscale;
 		ireq->rcv_wscale = rcv_wscale;
 	}
 	}
 
 
@@ -2544,7 +2552,8 @@ static void tcp_connect_init(struct sock *sk)
 				  &tp->rcv_wnd,
 				  &tp->rcv_wnd,
 				  &tp->window_clamp,
 				  &tp->window_clamp,
 				  sysctl_tcp_window_scaling,
 				  sysctl_tcp_window_scaling,
-				  &rcv_wscale);
+				  &rcv_wscale,
+				  dst_metric(dst, RTAX_INITRWND));
 
 
 	tp->rx_opt.rcv_wscale = rcv_wscale;
 	tp->rx_opt.rcv_wscale = rcv_wscale;
 	tp->rcv_ssthresh = tp->rcv_wnd;
 	tp->rcv_ssthresh = tp->rcv_wnd;

+ 2 - 1
net/ipv6/syncookies.c

@@ -269,7 +269,8 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
 	req->window_clamp = tp->window_clamp ? :dst_metric(dst, RTAX_WINDOW);
 	req->window_clamp = tp->window_clamp ? :dst_metric(dst, RTAX_WINDOW);
 	tcp_select_initial_window(tcp_full_space(sk), req->mss,
 	tcp_select_initial_window(tcp_full_space(sk), req->mss,
 				  &req->rcv_wnd, &req->window_clamp,
 				  &req->rcv_wnd, &req->window_clamp,
-				  ireq->wscale_ok, &rcv_wscale);
+				  ireq->wscale_ok, &rcv_wscale,
+				  dst_metric(dst, RTAX_INITRWND));
 
 
 	ireq->rcv_wscale = rcv_wscale;
 	ireq->rcv_wscale = rcv_wscale;