]> git.ipfire.org Git - thirdparty/openssh-portable.git/commitdiff
upstream: add a ssh_packet_process_read() function that reads from
authordjm@openbsd.org <djm@openbsd.org>
Sat, 22 Jan 2022 00:49:34 +0000 (00:49 +0000)
committerDamien Miller <djm@mindrot.org>
Tue, 25 Jan 2022 01:18:35 +0000 (12:18 +1100)
a fd directly into the transport input buffer.

Use this in the client and server mainloops to avoid unnecessary
copying. It also lets us use a more greedy read size without penalty.

Yields a 2-3% performance gain on cipher-speed.sh (in a fairly
unscientific test tbf)

feedback dtucker@ ok markus@

OpenBSD-Commit-ID: df4112125bf79d8e38e79a77113e1b373078e632

channels.h
clientloop.c
packet.c
packet.h
serverloop.c

index 420099ee2a703bc5f8574761a8f943bb0cb228d9..82f33ba2ff14be2b8d5e01c1cc6c68de53c6cbf2 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: channels.h,v 1.140 2022/01/06 21:48:38 djm Exp $ */
+/* $OpenBSD: channels.h,v 1.141 2022/01/22 00:49:34 djm Exp $ */
 
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -247,6 +247,9 @@ struct Channel {
 /* Read buffer size */
 #define CHAN_RBUF      (16*1024)
 
+/* Maximum size for direct reads to buffers */
+#define CHANNEL_MAX_READ       CHAN_SES_PACKET_DEFAULT
+
 /* Maximum channel input buffer size */
 #define CHAN_INPUT_MAX (16*1024*1024)
 
index 5145f011237e1cd554d9a59821cd35efa47bbbb2..fd190980577c69b19417a9263ddb72173d38cd59 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: clientloop.c,v 1.377 2022/01/21 07:04:19 djm Exp $ */
+/* $OpenBSD: clientloop.c,v 1.378 2022/01/22 00:49:34 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -630,40 +630,25 @@ client_suspend_self(struct sshbuf *bin, struct sshbuf *bout, struct sshbuf *berr
 static void
 client_process_net_input(struct ssh *ssh)
 {
-       char buf[SSH_IOBUFSZ];
-       int len;
+       int r;
 
        /*
         * Read input from the server, and add any such data to the buffer of
         * the packet subsystem.
         */
        schedule_server_alive_check();
-       /* Read as much as possible. */
-       len = read(connection_in, buf, sizeof(buf));
-       if (len == 0) {
-               /* Received EOF. The remote host has closed the connection. */
-               quit_message("Connection to %.300s closed by remote host.",
-                   host);
-               return;
-       }
-       /*
-        * There is a kernel bug on Solaris that causes poll to
-        * sometimes wake up even though there is no data available.
-        */
-       if (len == -1 &&
-           (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK))
-               len = 0;
-
-       if (len == -1) {
-               /*
-                * An error has encountered.  Perhaps there is a
-                * network problem.
-                */
-               quit_message("Read from remote host %s: %s",
-                   host, strerror(errno));
-               return;
+       if ((r = ssh_packet_process_read(ssh, connection_in)) == 0)
+               return; /* success */
+       if (r == SSH_ERR_SYSTEM_ERROR) {
+               if (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK)
+                       return;
+               if (errno == EPIPE) {
+                       quit_message("Connection to %s closed by remote host.",
+                           host);
+                       return;
+               }
        }
-       ssh_packet_process_incoming(ssh, buf, len);
+       quit_message("Read from remote host %s: %s", host, ssh_err(r));
 }
 
 static void
index 5a50fcd9569dcc4da314a3891ef91748f6d84112..bde6c1045e8a6562c280f20f99bf97f3d90800fd 100644 (file)
--- a/packet.c
+++ b/packet.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: packet.c,v 1.306 2022/01/21 06:58:06 djm Exp $ */
+/* $OpenBSD: packet.c,v 1.307 2022/01/22 00:49:34 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -1784,6 +1784,31 @@ ssh_packet_process_incoming(struct ssh *ssh, const char *buf, u_int len)
        return 0;
 }
 
+/* Reads and buffers data from the specified fd */
+int
+ssh_packet_process_read(struct ssh *ssh, int fd)
+{
+       struct session_state *state = ssh->state;
+       int r;
+       size_t rlen;
+
+       if ((r = sshbuf_read(fd, state->input, PACKET_MAX_SIZE, &rlen)) != 0)
+               return r;
+
+       if (state->packet_discard) {
+               if ((r = sshbuf_consume_end(state->input, rlen)) != 0)
+                       return r;
+               state->keep_alive_timeouts = 0; /* ?? */
+               if (rlen >= state->packet_discard) {
+                       if ((r = ssh_packet_stop_discard(ssh)) != 0)
+                               return r;
+               }
+               state->packet_discard -= rlen;
+               return 0;
+       }
+       return 0;
+}
+
 int
 ssh_packet_remaining(struct ssh *ssh)
 {
index 2ad0e70cfd791a74f411f6a18f37e1c76b32419c..176488b1e5d2f235c366dab1e970ac0617779c81 100644 (file)
--- a/packet.h
+++ b/packet.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: packet.h,v 1.93 2021/07/16 09:00:23 djm Exp $ */
+/* $OpenBSD: packet.h,v 1.94 2022/01/22 00:49:34 djm Exp $ */
 
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -128,6 +128,7 @@ int  ssh_packet_read_expect(struct ssh *, u_int type);
 int      ssh_packet_read_poll(struct ssh *);
 int ssh_packet_read_poll2(struct ssh *, u_char *, u_int32_t *seqnr_p);
 int     ssh_packet_process_incoming(struct ssh *, const char *buf, u_int len);
+int     ssh_packet_process_read(struct ssh *, int);
 int      ssh_packet_read_seqnr(struct ssh *, u_char *, u_int32_t *seqnr_p);
 int      ssh_packet_read_poll_seqnr(struct ssh *, u_char *, u_int32_t *seqnr_p);
 
index e31dbed55a7f351cff4b1e5263f4aef17d222d8b..15beac2de04cc81d24d39cc96eef469e86c5fc6c 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: serverloop.c,v 1.230 2022/01/06 21:55:23 djm Exp $ */
+/* $OpenBSD: serverloop.c,v 1.231 2022/01/22 00:49:34 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -272,27 +272,24 @@ wait_until_can_do_something(struct ssh *ssh,
 static int
 process_input(struct ssh *ssh, int connection_in)
 {
-       int r, len;
-       char buf[16384];
-
-       /* Read and buffer any input data from the client. */
-       len = read(connection_in, buf, sizeof(buf));
-       if (len == 0) {
-               verbose("Connection closed by %.100s port %d",
-                   ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
-               return -1;
-       } else if (len == -1) {
-               if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)
+       int r;
+
+       if ((r = ssh_packet_process_read(ssh, connection_in)) == 0)
+               return 0; /* success */
+       if (r == SSH_ERR_SYSTEM_ERROR) {
+               if (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK)
                        return 0;
+               if (errno == EPIPE) {
+                       verbose("Connection closed by %.100s port %d",
+                           ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
+                       return -1;
+               }
                verbose("Read error from remote host %s port %d: %s",
                    ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
                    strerror(errno));
                cleanup_exit(255);
        }
-       /* Buffer any received data. */
-       if ((r = ssh_packet_process_incoming(ssh, buf, len)) != 0)
-               fatal_fr(r, "ssh_packet_process_incoming");
-       return 0;
+       return -1;
 }
 
 /*