From mboxrd@z Thu Jan 1 00:00:00 1970 Message-ID: To: 9fans@cse.psu.edu From: rsc@plan9.bell-labs.com MIME-Version: 1.0 Content-Type: text/plain; charset="US-ASCII" Content-Transfer-Encoding: 7bit Subject: [9fans] your choice: nodelay or no pty Date: Tue, 14 May 2002 22:40:21 -0400 Topicbox-Message-UUID: 920e1b12-eaca-11e9-9e20-41e7f4b1d025 Here's an annoying Unix kludge. If someone has a better way to do this, I would love to hear about it. SSH, ever the good network citizen, insists on using Nagle's algorithm for non-interactive sessions. Thus, if you are using SSH to invoke u9fs or other RPC-based programs, latency suffers dramatically. The only way around this, short of editing the SSH source code on all the Unix platforms of interest and convincing the sysadmins to run your modfied sshd, is to run your binary stream programs using a pty, which tricks SSH into thinking your connection is interactive. Unfortunately, using a pty turns on all the terminal goo. You might try running stty raw as the first line of a shell script that starts u9fs on the remote machine, but that induces a race condition, where if the u9fs client is particularly fast, the first (binary) message will get echoed back in ASCIIfied binary. Thus, we have to get sshd to set up the terminal before any I/O happens. The diffs below add a -R option to ssh that means ``put the remote terminal in raw mode'' (the default is ``set up the remote terminal like a dumb terminal''). Once you have this, you can use ``ssh -Rmp'' instead of ``ssh'' to get a no-translation low-latency channel. Unfortunately, with a pty comes the merging of stdout and stderr. I see a factor of four speedup in reading files from u9fs over ssh using this. I see similar speedups in sshnet for proxied RPC-like network traffic. Enjoy. Russ diff -n /n/dump/2002/0514/sys/src/cmd/ssh . diff -n /n/dump/2002/0514/sys/src/cmd/ssh/cmsg.c ./cmsg.c /n/dump/2002/0514/sys/src/cmd/ssh/cmsg.c:333 a ./cmsg.c:334,363 > static uchar rawptyopt[] = > { > 30, 0, /* ignpar */ > 31, 0, /* parmrk */ > 32, 0, /* inpck */ > 33, 0, /* istrip */ > 34, 0, /* inlcr */ > 35, 0, /* igncr */ > 36, 0, /* icnrl */ > 37, 0, /* iuclc */ > 38, 0, /* ixon */ > 39, 1, /* ixany */ > 40, 0, /* ixoff */ > 41, 0, /* imaxbel */ > > 50, 0, /* isig: intr, quit, susp processing */ > 51, 0, /* icanon: erase and kill processing */ > 52, 0, /* xcase */ > > 53, 0, /* echo */ > > 57, 0, /* noflsh */ > 58, 0, /* tostop */ > 59, 0, /* iexten: impl defined control chars */ > > 70, 0, /* opost */ > > 0x00, > }; > /n/dump/2002/0514/sys/src/cmd/ssh/cmsg.c:352 c ./cmsg.c:382,385 < putbytes(m, ptyopt, sizeof ptyopt); --- > if(rawhack) > putbytes(m, rawptyopt, sizeof rawptyopt); > else > putbytes(m, ptyopt, sizeof ptyopt); diff -n /n/dump/2002/0514/sys/src/cmd/ssh/ssh.c ./ssh.c /n/dump/2002/0514/sys/src/cmd/ssh/ssh.c:7 a ./ssh.c:8 > int rawhack; /n/dump/2002/0514/sys/src/cmd/ssh/ssh.c:59 c ./ssh.c:60 < fprint(2, "usage: ssh [-CiImpr] [-A authlist] [-c cipherlist] [user@]hostname [cmd [args]]\n"); --- > fprint(2, "usage: ssh [-CiImPpRrvw] [-A authlist] [-c cipherlist] [user@]hostname [cmd [args]]\n"); /n/dump/2002/0514/sys/src/cmd/ssh/ssh.c:117 a ./ssh.c:119,121 > break; > case 'R': > rawhack = 1; diff -n /n/dump/2002/0514/sys/src/cmd/ssh/ssh.h ./ssh.h /n/dump/2002/0514/sys/src/cmd/ssh/ssh.h:244 a ./ssh.h:245 > int rawhack; diff -n /n/dump/2002/0514/sys/src/cmd/ssh/sshnet.c ./sshnet.c /n/dump/2002/0514/sys/src/cmd/ssh/sshnet.c:12 a ./sshnet.c:13 > int rawhack = 1; /n/dump/2002/0514/sys/src/cmd/ssh/sshnet.c:1068 a ./sshnet.c:1070 > requestpty(&c); /* turns on TCP_NODELAY on other side */