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
This commit is contained in:
Matt Johnston 2022-01-27 14:34:10 +08:00
parent 14bdd5a8ae
commit 1c8f00bd59
13 changed files with 38 additions and 73 deletions

View File

@ -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 {

View File

@ -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 */
}

View File

@ -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;
}

View File

@ -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();
}

View File

@ -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;

View File

@ -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"))
}

View File

@ -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;
}
}

17
netio.c
View File

@ -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;
}

View File

@ -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);

View File

@ -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 {

View File

@ -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:

View File

@ -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;

View File

@ -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