From 1c8f00bd5978abe89d8b2410fa6d5c14d7bf7b46 Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Thu, 27 Jan 2022 14:34:10 +0800 Subject: [PATCH] Leave non-interactive at default QoS class Lower class levels are less well defined, and non-interactive SSH can carry various different types of applications. This change also sets lowdelay class (AF21) earlier in an an outbound dbclient session --- channel.h | 10 ++-------- cli-chansession.c | 8 ++------ cli-main.c | 5 +++-- cli-session.c | 3 +++ cli-tcpfwd.c | 7 +++---- common-channel.c | 13 +++---------- common-session.c | 18 ++++-------------- netio.c | 17 +++++++---------- netio.h | 8 ++++---- svr-chansession.c | 5 +++-- svr-tcpfwd.c | 9 ++++----- tcp-accept.c | 7 ------- tcpfwd.h | 1 - 13 files changed, 38 insertions(+), 73 deletions(-) diff --git a/channel.h b/channel.h index 6e1e399..dd174aa 100644 --- a/channel.h +++ b/channel.h @@ -28,6 +28,7 @@ #include "includes.h" #include "buffer.h" #include "circbuffer.h" +#include "netio.h" #define SSH_OPEN_ADMINISTRATIVELY_PROHIBITED 1 #define SSH_OPEN_CONNECT_FAILED 2 @@ -41,13 +42,6 @@ struct ChanType; -enum dropbear_channel_prio { - DROPBEAR_CHANNEL_PRIO_INTERACTIVE, /* pty shell, x11 */ - DROPBEAR_CHANNEL_PRIO_UNKNOWABLE, /* tcp - can't know what's being forwarded */ - DROPBEAR_CHANNEL_PRIO_BULK, /* the rest - probably scp, rsync, git, or something */ - DROPBEAR_CHANNEL_PRIO_EARLY, /* channel is still being set up */ -}; - struct Channel { unsigned int index; /* the local channel index */ @@ -88,7 +82,7 @@ struct Channel { const struct ChanType* type; - enum dropbear_channel_prio prio; + enum dropbear_prio prio; }; struct ChanType { diff --git a/cli-chansession.c b/cli-chansession.c index 14a2779..73bee17 100644 --- a/cli-chansession.c +++ b/cli-chansession.c @@ -348,7 +348,6 @@ static int cli_init_stdpipe_sess(struct Channel *channel) { } static int cli_init_netcat(struct Channel *channel) { - channel->prio = DROPBEAR_CHANNEL_PRIO_UNKNOWABLE; return cli_init_stdpipe_sess(channel); } @@ -361,12 +360,9 @@ static int cli_initchansess(struct Channel *channel) { cli_setup_agent(channel); } #endif - if (cli_opts.wantpty) { send_chansess_pty_req(channel); - channel->prio = DROPBEAR_CHANNEL_PRIO_INTERACTIVE; - } else { - channel->prio = DROPBEAR_CHANNEL_PRIO_BULK; + channel->prio = DROPBEAR_PRIO_LOWDELAY; } send_chansess_shell_req(channel); @@ -375,7 +371,7 @@ static int cli_initchansess(struct Channel *channel) { cli_tty_setup(); channel->read_mangler = cli_escape_handler; cli_ses.last_char = '\r'; - } + } return 0; /* Success */ } diff --git a/cli-main.c b/cli-main.c index 5d0b9cf..b571b90 100644 --- a/cli-main.c +++ b/cli-main.c @@ -84,8 +84,9 @@ int main(int argc, char ** argv) { } else #endif { - progress = connect_remote(cli_opts.remotehost, cli_opts.remoteport, - cli_connected, &ses, cli_opts.bind_address, cli_opts.bind_port); + progress = connect_remote(cli_opts.remotehost, cli_opts.remoteport, + cli_connected, &ses, cli_opts.bind_address, cli_opts.bind_port, + DROPBEAR_PRIO_LOWDELAY); sock_in = sock_out = -1; } diff --git a/cli-session.c b/cli-session.c index 66352cc..2044b46 100644 --- a/cli-session.c +++ b/cli-session.c @@ -102,6 +102,9 @@ void cli_connected(int result, int sock, void* userdata, const char *errstring) dropbear_exit("Connect failed: %s", errstring); } myses->sock_in = myses->sock_out = sock; + TRACE(("cli_connected")) + ses.socket_prio = DROPBEAR_PRIO_NORMAL; + /* switches to lowdelay */ update_channel_prio(); } diff --git a/cli-tcpfwd.c b/cli-tcpfwd.c index e61a0c3..1b95615 100644 --- a/cli-tcpfwd.c +++ b/cli-tcpfwd.c @@ -51,7 +51,7 @@ static int cli_localtcp(const char* listenaddr, unsigned int remoteport); static const struct ChanType cli_chan_tcplocal = { "direct-tcpip", - tcp_prio_inithandler, + NULL, NULL, NULL, NULL, @@ -272,10 +272,9 @@ static int newtcpforwarded(struct Channel * channel) { goto out; } - channel->prio = DROPBEAR_CHANNEL_PRIO_UNKNOWABLE; - snprintf(portstring, sizeof(portstring), "%u", fwd->connectport); - channel->conn_pending = connect_remote(fwd->connectaddr, portstring, channel_connect_done, channel, NULL, NULL); + channel->conn_pending = connect_remote(fwd->connectaddr, portstring, channel_connect_done, + channel, NULL, NULL, DROPBEAR_PRIO_NORMAL); err = SSH_OPEN_IN_PROGRESS; diff --git a/common-channel.c b/common-channel.c index 047eece..be5b57f 100644 --- a/common-channel.c +++ b/common-channel.c @@ -162,7 +162,7 @@ static struct Channel* newchannel(unsigned int remotechan, newchan->recvdonelen = 0; newchan->recvmaxpacket = RECV_MAX_CHANNEL_DATA_LEN; - newchan->prio = DROPBEAR_CHANNEL_PRIO_EARLY; /* inithandler sets it */ + newchan->prio = DROPBEAR_PRIO_NORMAL; ses.channels[i] = newchan; ses.chancount++; @@ -955,9 +955,7 @@ void recv_msg_channel_open() { } } - if (channel->prio == DROPBEAR_CHANNEL_PRIO_EARLY) { - channel->prio = DROPBEAR_CHANNEL_PRIO_BULK; - } + update_channel_prio(); /* success */ send_msg_channel_open_confirmation(channel, channel->recvwindow, @@ -970,8 +968,6 @@ failure: cleanup: m_free(type); - - update_channel_prio(); TRACE(("leave recv_msg_channel_open")) } @@ -1166,11 +1162,8 @@ void recv_msg_channel_open_confirmation() { } } - if (channel->prio == DROPBEAR_CHANNEL_PRIO_EARLY) { - channel->prio = DROPBEAR_CHANNEL_PRIO_BULK; - } update_channel_prio(); - + TRACE(("leave recv_msg_channel_open_confirmation")) } diff --git a/common-session.c b/common-session.c index bfe6284..3d406b1 100644 --- a/common-session.c +++ b/common-session.c @@ -64,7 +64,7 @@ void common_session_init(int sock_in, int sock_out) { setnonblocking(sock_out); } - ses.socket_prio = DROPBEAR_PRIO_DEFAULT; + ses.socket_prio = DROPBEAR_PRIO_NORMAL; /* Sets it to lowdelay */ update_channel_prio(); @@ -667,26 +667,16 @@ void update_channel_prio() { return; } - new_prio = DROPBEAR_PRIO_BULK; + new_prio = DROPBEAR_PRIO_NORMAL; for (i = 0; i < ses.chansize; i++) { struct Channel *channel = ses.channels[i]; - if (!channel || channel->prio == DROPBEAR_CHANNEL_PRIO_EARLY) { - if (channel && channel->prio == DROPBEAR_CHANNEL_PRIO_EARLY) { - TRACE(("update_channel_prio: early %d", channel->index)) - } + if (!channel) { continue; } any = 1; - if (channel->prio == DROPBEAR_CHANNEL_PRIO_INTERACTIVE) - { - TRACE(("update_channel_prio: lowdelay %d", channel->index)) + if (channel->prio == DROPBEAR_PRIO_LOWDELAY) { new_prio = DROPBEAR_PRIO_LOWDELAY; break; - } else if (channel->prio == DROPBEAR_CHANNEL_PRIO_UNKNOWABLE - && new_prio == DROPBEAR_PRIO_BULK) - { - TRACE(("update_channel_prio: unknowable %d", channel->index)) - new_prio = DROPBEAR_PRIO_DEFAULT; } } diff --git a/netio.c b/netio.c index 4f0a5fd..d466de5 100644 --- a/netio.c +++ b/netio.c @@ -20,6 +20,7 @@ struct dropbear_progress_connection { char* errstring; char *bind_address, *bind_port; + enum dropbear_prio prio; }; /* Deallocate a progress connection. Removes from the pending list if iter!=NULL. @@ -110,6 +111,7 @@ static void connect_try_next(struct dropbear_progress_connection *c) { ses.maxfd = MAX(ses.maxfd, c->sock); set_sock_nodelay(c->sock); + set_sock_priority(c->sock, c->prio); setnonblocking(c->sock); #if DROPBEAR_CLIENT_TCP_FAST_OPEN @@ -172,8 +174,8 @@ static void connect_try_next(struct dropbear_progress_connection *c) { /* Connect via TCP to a host. */ struct dropbear_progress_connection *connect_remote(const char* remotehost, const char* remoteport, - connect_callback cb, void* cb_data, - const char* bind_address, const char* bind_port) + connect_callback cb, void* cb_data, + const char* bind_address, const char* bind_port, enum dropbear_prio prio) { struct dropbear_progress_connection *c = NULL; int err; @@ -185,6 +187,7 @@ struct dropbear_progress_connection *connect_remote(const char* remotehost, cons c->sock = -1; c->cb = cb; c->cb_data = cb_data; + c->prio = prio; list_append(&ses.conn_pending, c); @@ -378,10 +381,8 @@ void set_sock_priority(int sock, enum dropbear_prio prio) { /* Set the DSCP field for outbound IP packet priority. rfc4594 has some guidance to meanings. - We set AF21 as "Low-Latency" class for interactive (tty session). - Set AF11 "High-Throughput" for bulk data (which includes things - such as git over ssh). We usually want higher priority than - CS1/LE least effort. + We set AF21 as "Low-Latency" class for interactive (tty session, + also handshake/setup packets). Other traffic is left at the default. OpenSSH at present uses AF21/CS1, rationale https://cvsweb.openbsd.org/src/usr.bin/ssh/readconf.c#rev1.284 @@ -391,8 +392,6 @@ void set_sock_priority(int sock, enum dropbear_prio prio) { */ if (prio == DROPBEAR_PRIO_LOWDELAY) { val = IPTOS_DSCP_AF21; - } else if (prio == DROPBEAR_PRIO_BULK) { - val = IPTOS_DSCP_AF11; } else { val = 0; /* default */ } @@ -412,8 +411,6 @@ void set_sock_priority(int sock, enum dropbear_prio prio) { /* Set scheduling priority within the local Linux network stack */ if (prio == DROPBEAR_PRIO_LOWDELAY) { val = TC_PRIO_INTERACTIVE; - } else if (prio == DROPBEAR_PRIO_BULK) { - val = TC_PRIO_BULK; } else { val = 0; } diff --git a/netio.h b/netio.h index d61ef5e..605512b 100644 --- a/netio.h +++ b/netio.h @@ -6,9 +6,8 @@ #include "queue.h" enum dropbear_prio { - DROPBEAR_PRIO_DEFAULT = 10, - DROPBEAR_PRIO_LOWDELAY = 11, - DROPBEAR_PRIO_BULK = 12, + DROPBEAR_PRIO_NORMAL = 0, /* the rest - tcp-fwd, scp, rsync, git, etc */ + DROPBEAR_PRIO_LOWDELAY, /* pty shell, x11 */ }; void set_sock_nodelay(int sock); @@ -30,7 +29,8 @@ typedef void(*connect_callback)(int result, int sock, void* data, const char* er /* Always returns a progress connection, if it fails it will call the callback at a later point */ struct dropbear_progress_connection * connect_remote (const char* remotehost, const char* remoteport, - connect_callback cb, void *cb_data, const char* bind_address, const char* bind_port); + connect_callback cb, void *cb_data, const char* bind_address, const char* bind_port, + enum dropbear_prio prio); /* Sets up for select() */ void set_connect_fds(fd_set *writefd); diff --git a/svr-chansession.c b/svr-chansession.c index 6c29b17..e0e1d31 100644 --- a/svr-chansession.c +++ b/svr-chansession.c @@ -277,7 +277,8 @@ static int newchansess(struct Channel *channel) { chansess->agentdir = NULL; #endif - channel->prio = DROPBEAR_CHANNEL_PRIO_INTERACTIVE; + /* Will drop to DROPBEAR_PRIO_NORMAL if a non-tty command starts */ + channel->prio = DROPBEAR_PRIO_LOWDELAY; return 0; @@ -734,7 +735,7 @@ static int sessioncommand(struct Channel *channel, struct ChanSess *chansess, /* no pty */ ret = noptycommand(channel, chansess); if (ret == DROPBEAR_SUCCESS) { - channel->prio = DROPBEAR_CHANNEL_PRIO_BULK; + channel->prio = DROPBEAR_PRIO_NORMAL; update_channel_prio(); } } else { diff --git a/svr-tcpfwd.c b/svr-tcpfwd.c index 9c1edd4..4aa3152 100644 --- a/svr-tcpfwd.c +++ b/svr-tcpfwd.c @@ -60,7 +60,7 @@ static int newtcpdirect(struct Channel * channel); #if DROPBEAR_SVR_REMOTETCPFWD static const struct ChanType svr_chan_tcpremote = { "forwarded-tcpip", - tcp_prio_inithandler, + NULL, NULL, NULL, NULL, @@ -289,11 +289,10 @@ static int newtcpdirect(struct Channel * channel) { goto out; } - channel->prio = DROPBEAR_CHANNEL_PRIO_UNKNOWABLE; - snprintf(portstring, sizeof(portstring), "%u", destport); - channel->conn_pending = connect_remote(desthost, portstring, channel_connect_done, channel, NULL, NULL); - + channel->conn_pending = connect_remote(desthost, portstring, channel_connect_done, + channel, NULL, NULL, DROPBEAR_PRIO_NORMAL); + err = SSH_OPEN_IN_PROGRESS; out: diff --git a/tcp-accept.c b/tcp-accept.c index 6578d71..73cfa54 100644 --- a/tcp-accept.c +++ b/tcp-accept.c @@ -45,13 +45,6 @@ static void cleanup_tcp(const struct Listener *listener) { m_free(tcpinfo); } -int tcp_prio_inithandler(struct Channel* channel) -{ - TRACE(("tcp_prio_inithandler channel %d", channel->index)) - channel->prio = DROPBEAR_CHANNEL_PRIO_UNKNOWABLE; - return 0; -} - static void tcp_acceptor(const struct Listener *listener, int sock) { int fd; diff --git a/tcpfwd.h b/tcpfwd.h index fa81fa4..69e5af2 100644 --- a/tcpfwd.h +++ b/tcpfwd.h @@ -71,7 +71,6 @@ void cli_recv_msg_request_failure(void); /* Common */ int listen_tcpfwd(struct TCPListener* tcpinfo, struct Listener **ret_listener); -int tcp_prio_inithandler(struct Channel* chan); /* A random identifier */ #define CHANNEL_ID_TCPFORWARDED 0x43612c67