Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions mfd_connect/ssh.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import codecs
import logging
import random
import socket
import sys
from shlex import quote
import time
Expand Down Expand Up @@ -136,6 +137,13 @@ def _connect(self) -> None:
:raises OsNotSupported: if os not found in available process classes
"""
self._connection.connect(**self._connection_details, compress=True)
# Disable Nagle's algorithm on the transport socket. Without TCP_NODELAY the small
# exec/exit-status packets hit TCP delayed-ACK stalls (~40 ms each), roughly doubling
# per-command latency. This changes packet batching only - command semantics,
# timeouts, return codes and output are unaffected.
transport = self._connection.get_transport()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found one doubt. In case of using SSHConfigConnection with ProxyJump, transport.sock is a Paramiko Channel, not a native TCP socket. SSHConfigConnection._connect() passes the proxy channel via the sock argument, and Paramiko retains it as transport.sock.

Since Channel does not implement setsockopt(), it passes the None checks but raises AttributeError: 'Channel' object has no attribute 'setsockopt' here after successful authentication. This breaks initialization and reconnection for ProxyJump connections using the normal authentication path.

Could we restrict this optimization to native TCP sockets and add a regression test with a channel-backed transport? The existing test_connect_injects_sock_for_proxied mocks SSHConnection._connect(), so it does not exercise this new call.

if transport is not None and transport.sock is not None:
transport.sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
Comment on lines +142 to +146
key_auth = str(self._connection.get_transport())
if "awaiting auth" in key_auth:
logger.log(level=log_levels.MODULE_DEBUG, msg="SSH server requested additional authentication")
Expand Down
Loading