DynamicWindow Patch

Michael Stevens stevensm at gmail.com
Thu Jul 8 04:51:53 EST 2004


We have developed a patch that enables changing the SSH window size
using the tcp window size as the source. This allows SSH to obtain
maximum use of the bandwidth on high BDP links.

We also have a page that describes the changes and performance.
http://www.psc.edu/~rapier/hpn-ssh/

The patch against CVS is included here.


Common subdirectories: src/usr.bin/ssh/CVS and ssh/CVS
diff -u src/usr.bin/ssh/buffer.c ssh/buffer.c
--- src/usr.bin/ssh/buffer.c	2003-11-21 06:57:03.000000000 -0500
+++ ssh/buffer.c	2004-07-07 10:04:27.000000000 -0400
@@ -18,6 +18,14 @@
 #include "buffer.h"
 #include "log.h"
 
+static int unlimited = 0;
+
+void 
+set_unlimited(Buffer *buffer, int new_value)
+{
+	buffer->unlimited = new_value;
+}
+
 /* Initializes the buffer structure. */
 
 void
@@ -30,6 +38,7 @@
 	buffer->alloc = len;
 	buffer->offset = 0;
 	buffer->end = 0;
+	buffer->unlimited = 0;
 }
 
 /* Frees any memory used for the buffer. */
@@ -78,7 +87,7 @@
 	u_int newlen;
 	void *p;
 
-	if (len > 0x100000)
+	if (!buffer->unlimited && len > 0x100000)
 		fatal("buffer_append_space: len %u not supported", len);
 
 	/* If the buffer is empty, start using it from the beginning. */
@@ -107,7 +116,7 @@
 	/* Increase the size of the buffer and retry. */
 
 	newlen = buffer->alloc + len + 32768;
-	if (newlen > 0xa00000)
+	if (!buffer->unlimited && newlen > 0xa00000)
 		fatal("buffer_append_space: alloc %u not supported",
 		    newlen);
 	buffer->buf = xrealloc(buffer->buf, newlen);
diff -u src/usr.bin/ssh/buffer.h ssh/buffer.h
--- src/usr.bin/ssh/buffer.h	2002-03-04 12:27:39.000000000 -0500
+++ ssh/buffer.h	2004-07-07 10:02:24.000000000 -0400
@@ -21,8 +21,11 @@
 	u_int	 alloc;		/* Number of bytes allocated for data. */
 	u_int	 offset;	/* Offset of first byte containing data. */
 	u_int	 end;		/* Offset of last byte containing data. */
+	u_int	 unlimited;
 }       Buffer;
 
+void set_unlimited(Buffer *,int);
+
 void	 buffer_init(Buffer *);
 void	 buffer_clear(Buffer *);
 void	 buffer_free(Buffer *);
diff -u src/usr.bin/ssh/channels.c ssh/channels.c
--- src/usr.bin/ssh/channels.c	2004-06-13 21:44:38.000000000 -0400
+++ ssh/channels.c	2004-07-07 10:02:24.000000000 -0400
@@ -255,6 +255,7 @@
 	c->local_window_max = window;
 	c->local_consumed = 0;
 	c->local_maxpacket = maxpack;
+	c->dynamic_window = 0;
 	c->remote_id = -1;
 	c->remote_name = xstrdup(remote_name);
 	c->remote_window = 0;
@@ -1520,14 +1521,26 @@
 	    !(c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD)) &&
 	    c->local_window < c->local_window_max/2 &&
 	    c->local_consumed > 0) {
+		u_int32_t tcpwinsz = 0;
+		socklen_t optsz = sizeof(tcpwinsz);
+		int ret = -1;
+		u_int32_t addition = 0;
+		if (c->dynamic_window)
+			ret = getsockopt(packet_get_connection_in(), 
+				SOL_SOCKET, SO_RCVBUF, &tcpwinsz, &optsz);
+		if (c->dynamic_window && (ret == 0) && 
+		    (tcpwinsz > c->local_window_max)) {
+			addition = 2 * tcpwinsz - c->local_window_max;
+			c->local_window_max += addition;
+		}
 		packet_start(SSH2_MSG_CHANNEL_WINDOW_ADJUST);
 		packet_put_int(c->remote_id);
-		packet_put_int(c->local_consumed);
+		packet_put_int(c->local_consumed + addition);
 		packet_send();
 		debug2("channel %d: window %d sent adjust %d",
 		    c->self, c->local_window,
 		    c->local_consumed);
-		c->local_window += c->local_consumed;
+		c->local_window += c->local_consumed + addition;
 		c->local_consumed = 0;
 	}
 	return 1;
Only in ssh: channels.c~
diff -u src/usr.bin/ssh/channels.h ssh/channels.h
--- src/usr.bin/ssh/channels.h	2004-06-13 11:03:02.000000000 -0400
+++ ssh/channels.h	2004-07-07 10:02:24.000000000 -0400
@@ -97,6 +97,7 @@
 	u_int	local_window_max;
 	u_int	local_consumed;
 	u_int	local_maxpacket;
+	int	dynamic_window;
 	int     extended_usage;
 	int	single_connection;
 
Common subdirectories: src/usr.bin/ssh/lib and ssh/lib
Common subdirectories: src/usr.bin/ssh/scard and ssh/scard
Common subdirectories: src/usr.bin/ssh/scp and ssh/scp
diff -u src/usr.bin/ssh/serverloop.c ssh/serverloop.c
--- src/usr.bin/ssh/serverloop.c	2004-05-21 07:33:11.000000000 -0400
+++ ssh/serverloop.c	2004-07-07 10:02:24.000000000 -0400
@@ -892,6 +892,9 @@
 	c = channel_new("session", SSH_CHANNEL_LARVAL,
 	    -1, -1, -1, /*window size*/0, CHAN_SES_PACKET_DEFAULT,
 	    0, "server-session", 1);
+	set_unlimited(&c->input,1);
+	set_unlimited(&c->output,1);
+	c->dynamic_window = 1;
 	if (session_open(the_authctxt, c->self) != 1) {
 		debug("session open failed, free channel %d", c->self);
 		channel_free(c);
Only in ssh: serverloop.c~
Common subdirectories: src/usr.bin/ssh/sftp and ssh/sftp
Common subdirectories: src/usr.bin/ssh/sftp-server and ssh/sftp-server
Common subdirectories: src/usr.bin/ssh/ssh and ssh/ssh
Common subdirectories: src/usr.bin/ssh/ssh-add and ssh/ssh-add
Common subdirectories: src/usr.bin/ssh/ssh-agent and ssh/ssh-agent
Common subdirectories: src/usr.bin/ssh/ssh-keygen and ssh/ssh-keygen
Common subdirectories: src/usr.bin/ssh/ssh-keyscan and ssh/ssh-keyscan
Common subdirectories: src/usr.bin/ssh/ssh-keysign and ssh/ssh-keysign
diff -u src/usr.bin/ssh/ssh.c ssh/ssh.c
--- src/usr.bin/ssh/ssh.c	2004-06-13 11:03:02.000000000 -0400
+++ ssh/ssh.c	2004-07-07 10:02:24.000000000 -0400
@@ -1125,7 +1125,11 @@
 	    "session", SSH_CHANNEL_OPENING, in, out, err,
 	    window, packetmax, CHAN_EXTENDED_WRITE,
 	    "client-session", /*nonblock*/0);
-
+	if (!tty_flag) {
+		c->dynamic_window = 1;
+		set_unlimited(&c->input,1);
+		set_unlimited(&c->output,1);
+	}
 	debug3("ssh_session2_open: channel_new: %d", c->self);
 
 	channel_send_open(c->self);
Only in ssh: ssh.c~
Common subdirectories: src/usr.bin/ssh/sshd and ssh/sshd




More information about the openssh-unix-dev mailing list