[PATCH] Update default QoS markers for ssh

Job Snijders job at openbsd.org
Tue Apr 3 01:48:50 AEST 2018


(posting from tech at openbsd.org taken here for discussion in wider audience)

Dear all,

There may be opportunity for improvement of ssh(1) and sshd(8)'s default
QoS markers for better integration in environments that can offer either
layer-2 or layer-3 prioritisation profiles. Currently ssh(1) and sshd(8)
set obsoleted values 'lowdelay' for interactive sessions and
'throughput' for non-interactive sessions.

TL;DR: I propose to update the defaults to use DSCP "AF21" (Low Latency
Data) for interactive session traffic, and CS1 ("Lower Effort") for
non-interactive traffic. This applies to both IPv4 and IPv6.

The openbsd 'lowdelay' value translates to IP TOS '0x10', and
'throughput' translates to IP TOS 0x08'. The IP TOS field is 8 bits, and
was defined in RFC 1349 (1992 A.D.). IP TOS was deprecated in RFC 2474
(1998 A.D.) with the introduction of "Differentiated Services Field" aka
DSCP.

When the world transitioned from TOS to DSCP, the IP TOS field was
chopped up into two parts: the 6 most significant bits became the
DSField (which contains a DSCP), and the 2 least significant bits became
a place for ECN experimentation. (Similarly in IPv6, the 'Traffic Class'
became the DSField). To convert the IP TOS value to a DSCP value you
shift the value 2 bits to the right: 'lowdelay' = DSCP 0x04 and
'throughput' = DSCP 0x02. It should be noted that DSCP 0x04 and DSCP
0x02 have no meaning. Both 0x02 and 0x04 map to Precedence "routine",
which is the /least/ important Precedence.

Using IP TOS values is problematic because network operators can't match
on TOS values on today's equipment. We looked at Cisco IOS XR, Juniper
Junos, and Nokia SR-OS - and there aren't classifiers to match on TOS
values. Instead, the systems I mentioned allow you to match on DSCP
value (and perhaps IPv4 precedence).

The ability to correctly match QoS markers of this nature is important
in controlled environments, you'll generally see that the DSCP values
are fully trusted, or not honored at all (such as when crossing Internet
boundaries). An example would be how traffic from VOIP phones/apps are
treated in enterprise office networks, perhaps even in the entire branch
network. The industry practise is that iff QoS markers are honored, they
are translated 1:1 - so AF21 goes into AF21 (or equivalent).

I selected AF21 as this is the highest priority within the low-latency
service class (and it is higher than what we have today). SSH is elastic
and time-sensitive data, where a user is waiting for a response via the
network in order to continue with a task at hand. As such, these flows
should be considered foreground traffic, with delays or drops to such
traffic directly impacting user-productivity.

You may ask, "why not EF?" - the risk with EF is that you can easily end
up in a tiny policer queue, as an example some CPEs by default only
allow up to 100Kbps of EF traffic. EF is meant for inelastic traffic,
where for instance the codec sends packets at the rate the codec
produces them, regardless of availability of capacity.

For bulk SSH traffic, the "Lower Effort" marker was chosen to enable
networks implementing a scavanger/lower-than-best effort class to
discriminate scp(1) below normal activities, such as web surfing. In
general this type of bulk SSH traffic is a background activity. Today
this traffic would go into 'best effort', potentially drowning out other
traffic on wireless links, so kicking this into 'background' may improve
the user experience.

An advantage of using "AF21" for interactive SSH and "CS1" for bulk SSH
is that they are recognisable values on all common platforms (IANA
https://www.iana.org/assignments/dscp-registry/dscp-registry.xml ), and
for AF21 specifically a rigorous definition of the intended behavior
exists https://tools.ietf.org/html/rfc4594#section-4.7 in addition to
the definition of the Assured Forwarding PHB group
https://tools.ietf.org/html/rfc2597, and for CS1 (Lower Effort) there is
https://tools.ietf.org/html/rfc3662 - finally this document is also a
recommened reading: https://tools.ietf.org/html/rfc8325

Another advantage is that the first three bits of "AF21" map to the
equivalent IEEEE 802.1D PCP, IEEE 802.11e, MPLS EXP/Cos and IP
Precedence value of 2 (also known as "Immediate", or "AC_BE"), and CS1's
first 3 bits map to IEEEE 802.1D PCP, IEEE 802.11e, MPLS/Cos and IP
Precedence value 1 ("Background" or "AC_BK"). 

The below patch ensures that in environments where people are using QoS,
the openssh defaults can easily matched both for interactive and bulk
SSH traffic in all layers of the transport stack (wired/wirless
Ethernet, MPLS, IP) and priortize accordingly.

Kind regards,

Job

The below patch should be portable, but I've only tested it on my own
openbsd machines.

 usr.bin/ssh/readconf.c    | 4 ++--
 usr.bin/ssh/servconf.c    | 4 ++--
 usr.bin/ssh/ssh_config.5  | 6 ++++--
 usr.bin/ssh/sshd_config.5 | 6 ++++--
 4 files changed, 12 insertions(+), 8 deletions(-)

diff --git usr.bin/ssh/readconf.c usr.bin/ssh/readconf.c
index 5d17b725600..d3a121373d8 100644
--- usr.bin/ssh/readconf.c
+++ usr.bin/ssh/readconf.c
@@ -1981,9 +1981,9 @@ fill_default_options(Options * options)
 	if (options->visual_host_key == -1)
 		options->visual_host_key = 0;
 	if (options->ip_qos_interactive == -1)
-		options->ip_qos_interactive = IPTOS_LOWDELAY;
+		options->ip_qos_interactive = IPTOS_DSCP_AF21;
 	if (options->ip_qos_bulk == -1)
-		options->ip_qos_bulk = IPTOS_THROUGHPUT;
+		options->ip_qos_bulk = IPTOS_DSCP_CS1;
 	if (options->request_tty == -1)
 		options->request_tty = REQUEST_TTY_AUTO;
 	if (options->proxy_use_fdpass == -1)
diff --git usr.bin/ssh/servconf.c usr.bin/ssh/servconf.c
index 69c17907317..48354fda822 100644
--- usr.bin/ssh/servconf.c
+++ usr.bin/ssh/servconf.c
@@ -351,9 +351,9 @@ fill_default_server_options(ServerOptions *options)
 	if (options->permit_tun == -1)
 		options->permit_tun = SSH_TUNMODE_NO;
 	if (options->ip_qos_interactive == -1)
-		options->ip_qos_interactive = IPTOS_LOWDELAY;
+		options->ip_qos_interactive = IPTOS_DSCP_AF21;
 	if (options->ip_qos_bulk == -1)
-		options->ip_qos_bulk = IPTOS_THROUGHPUT;
+		options->ip_qos_bulk = IPTOS_DSCP_CS1;
 	if (options->version_addendum == NULL)
 		options->version_addendum = xstrdup("");
 	if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
diff --git usr.bin/ssh/ssh_config.5 usr.bin/ssh/ssh_config.5
index 71705cabdda..8989675d512 100644
--- usr.bin/ssh/ssh_config.5
+++ usr.bin/ssh/ssh_config.5
@@ -984,9 +984,11 @@ If one argument is specified, it is used as the packet class unconditionally.
 If two values are specified, the first is automatically selected for
 interactive sessions and the second for non-interactive sessions.
 The default is
-.Cm lowdelay
+.Cm af21
+.Ar (Low-Latency Data)
 for interactive sessions and
-.Cm throughput
+.Cm CS1
+.Ar (Lower Effort)
 for non-interactive sessions.
 .It Cm KbdInteractiveAuthentication
 Specifies whether to use keyboard-interactive authentication.
diff --git usr.bin/ssh/sshd_config.5 usr.bin/ssh/sshd_config.5
index e051df91254..ebf6f0c0c74 100644
--- usr.bin/ssh/sshd_config.5
+++ usr.bin/ssh/sshd_config.5
@@ -817,9 +817,11 @@ If one argument is specified, it is used as the packet class unconditionally.
 If two values are specified, the first is automatically selected for
 interactive sessions and the second for non-interactive sessions.
 The default is
-.Cm lowdelay
+.Cm af21
+.Ar (Low-Latency Data)
 for interactive sessions and
-.Cm throughput
+.Cm CS1
+.Ar (Lower Effort)
 for non-interactive sessions.
 .It Cm KbdInteractiveAuthentication
 Specifies whether to allow keyboard-interactive authentication.


More information about the openssh-unix-dev mailing list