Bug 1997 - Add QoS to ControlPath escapes
Summary: Add QoS to ControlPath escapes
Status: NEW
Alias: None
Product: Portable OpenSSH
Classification: Unclassified
Component: ssh (show other bugs)
Version: 5.9p1
Hardware: All All
: P2 enhancement
Assignee: Assigned to nobody
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-04-09 21:00 AEST by Peter Lebbing
Modified: 2020-05-29 20:56 AEST (History)
3 users (show)

See Also:


Attachments
Patch implementing %q QoS ControlPath escape (993 bytes, patch)
2012-04-09 21:00 AEST, Peter Lebbing
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Peter Lebbing 2012-04-09 21:00:19 AEST
Created attachment 2143 [details]
Patch implementing %q QoS ControlPath escape

I would like a percent-escape for the QoS used for the ControlPath, such that, for instance:

ControlMaster auto
ControlPath /home/peter/.ssh/control-%r@%h:%p-%q

would have %q expand to the (numerical) QoS value used, giving different control sockets for different QoS settings used for the master connection.

I have QoS and traffic shaping configured on an ADSL connection. When I have a shell open through ssh, it will create a connection with "interactive", i.e. high, priority. If I then start an rsync to the same remote machine, it ought to use "bulk", i.e. low, priority. Unfortunately it will use the master connection and blast all its data at interactive priority, which is not intended at all.

Having a percent escape for the QoS seems to me like an effective way to prevent this problem and still get great use out of the multiplexing feature. Using numerical QoS values gives greater flexibility than just discriminating between SSH's concept of interactive and non-interactive sessions as used in the IPQoS config option.

I just had a quick browse in the source code. Currently, the knowledge if the session is interactive/non-interactive is not yet available when the ControlPath percent escapes are parsed. Unfortunately, interactivity is only determined /after/ the connection has been established, and depends on whether the remote side allows allocation of a pty or X11 forwarding.

I have created a patch, but I am not familiar with the source, so perhaps it is very wrong :). Only the intention of interactivity is checked, not if a pty or X11 forwarding actually succeeded, since that information is not available. This also means that the %q might not match with the actual QoS used, since the latter depends on succesfully allocating a pty/X11 forwarding.

Thanks to the developers for all your work on SSH!

Peter.
Comment 1 Damien Miller 2012-07-06 10:57:03 AEST
The problem with this is that the QoS isn't always known when the connection is started. We have options for interactive and non-interactive QoS values, and the decision of whether a connection is interactive can happen well after the time when the connection is established - e.g. a multiplexed connection or no-shell sessions that is used for X11 forwarding.

IMO you would be better off defining multiple "Host" entries in ssh_config for your targets that forced the use of specific QoS and baked these into the hostname and ControlPath.
Comment 2 Peter Lebbing 2012-07-08 22:49:22 AEST
(In reply to comment #1)
> The problem with this is that the QoS isn't always known when the
> connection is started. We have options for interactive and
> non-interactive QoS values, and the decision of whether a connection
> is interactive can happen well after the time when the connection is
> established - e.g. a multiplexed connection or no-shell sessions
> that is used for X11 forwarding.

The whole problem is exactly that the QoS in the current situation already goes wrong with a multiplexed connection. The decision whether a connection is interactive is already too late: the session that started the multiplexed connection now determines the QoS for all other sessions that run over the same multiplexed connection.

So instead of completely ignoring the difference in the two arguments to IPQoS for all sessions that join the multiplexed connection, the ControlPath escape mitigates the problem. It would still get it wrong in some situations.[1] 

> IMO you would be better off defining multiple "Host" entries in
> ssh_config for your targets that forced the use of specific QoS and
> baked these into the hostname and ControlPath.

That would work. But it needs entries for all systems you wish to use with multiplexing. And I'd probably add a final entry for each host, matching the real unqualified and qualified hostnames and turning off multiplexing. So you don't accidentally blast all your data at the interactive QoS when you specify the real hostname.

Thanks for your input.

[1] If I look at my own usage pattern, those situations seem to be rare. Am I correct in thinking they are mostly related to the server forcing a setting you didn't request? Like not getting a pty or X forwarding.
Comment 3 chrysn 2020-05-21 05:15:31 AEST
Given the approach of distinguishing sockets based on their QoS has not led to a solution (with different hosts being a workaround but IMO not a well maintainable one), I've run through the sequence and options with the current versions:

* QoS is still decided after expansion (expansion happens in main; QoS is set down from there in ssh_session2 / ssh_session2_open / ssh_session2_setup)
* QoS, unless explicitly configured, is set to interactive based on the presence of tty_flag || a successful X forwarding.
* tty_flag is set in main based on -t/-T, the presence of a command and isatty a few lines before the control path expansion.

It should thus be relatively straight-forward to add a token for "is an interactive session" that would lack the QoS solution's fine-grainedness (but that comes to play only when explicit QoS configuration is around anyway, in which case setting the socket would often be possible in the same config stanca) and its reactivity to the presence of X forwarding.

Would a patch to add a "%I" for "1 for interactive sessions, 0 otherwise" to the expansion be generally acceptable? Peter, would it still serve your purposes (given your description sounded like the added flexibility is more of a bonus than a requirement)? If so, I'd be happy to write it.

Would it make sense to make the condition `options.forward_x11 || tty_flag` rather than plain `tty_flag` to capture the intention of the forwarding? (I'd rather not, though, as that'd have corner cases of X11-requested-and-not-granted leading to the wrong priority on the interactive control master, and would force all connections through the interactiv path if ForwardX11 is generally enabled; maybe a '%X' could later be considered for the benefit of those cases, but for here I'd like to keep it simple.)
Comment 4 Peter Lebbing 2020-05-29 20:56:56 AEST
(In reply to chrysn from comment #3)

Sorry for not replying sooner, it slipped my mind!

> Would a patch to add a "%I" for "1 for interactive sessions, 0
> otherwise" to the expansion be generally acceptable? Peter, would it
> still serve your purposes (given your description sounded like the
> added flexibility is more of a bonus than a requirement)?

Yes, that sounds fine! It would serve my purposes well. My personal preference would go not to 1/0 but something like I/NI for Interactive/Non-Interactive or something like that. But that's just a minor matter of preference. 1/0 works fine as well.

> If so, I'd be happy to write it.

That would be great!

> Would it make sense to make the condition `options.forward_x11 ||
> tty_flag` rather than plain `tty_flag` to capture the intention of
> the forwarding?

I think I agree that it's better not to do this. Especially the case of a globally enabled ForwardX11 is worrying to me.

FWIW, I came up with a workaround to get my priorities straight ;-). The case where I want to have concurrent interactive and bulk connections is almost always with rsync. So I have this:

~/.ssh/config:
--8<---------------cut here---------------start------------->8---
Host *
ControlMaster auto
ControlPath /home/peter/.ssh/control-%r@%h:%p
--8<---------------cut here---------------end--------------->8---

~/.profile:
--8<---------------cut here---------------start------------->8---
export RSYNC_RSH="ssh -o ControlPath=/home/peter/.ssh/rsync-control-%r@%h:%p"
--8<---------------cut here---------------end--------------->8---

This has an interesting side-effect: rsync auto-completion in bash uses the interactive ControlMaster! Which is fine, since auto-completion /is/ interactive. It turns out the completion actually uses ssh and ls to do its work, not rsync, and auto-completion of remote paths is turned off if rsync has an -e/-rsh argument. I am certainly not going to tell them to check RSYNC_RSH as well! :-)

With an open interactive ControlMaster, auto-completion is much quicker.

Thanks,

Peter.