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