Skip to content

LDAPConnectionHandler2 ignores use-tcp-keep-alive, use-tcp-no-delay, buffer-size and num-request-handlers, and applies allow-tcp-reuse-address only to its pre-check #1119

Description

@vharseko

Summary

org.forgerock.opendj.reactive.LDAPConnectionHandler2, the class every shipped LDAP listener runs on (opendj-server-legacy/resource/config/config.ldif, lines 316 and 340), never reads four properties of its own configuration: use-tcp-keep-alive, use-tcp-no-delay, buffer-size and num-request-handlers. A fifth one, allow-tcp-reuse-address, is only half applied. dsconfig accepts any value for them, the configuration entry stores it, and the handler keeps the same behaviour. Nothing in the configuration reference or in the server output tells the administrator that the setting has no effect.

The legacy org.opends.server.protocols.ldap.LDAPConnectionHandler does apply all five, so the properties only work on the handler that no fresh install uses.

Cause

LDAPConnectionHandler2.startListener() builds the LDAPListener with only two options taken from the configuration (LDAPConnectionHandler2.java, lines 683-685):

Options.defaultOptions()
       .set(LDAPListener.CONNECT_MAX_BACKLOG, backlog)
       .set(LDAPListener.REQUEST_MAX_SIZE_IN_BYTES, (int) currentConfig.getMaxRequestSize())

None of isUseTCPKeepAlive(), isUseTCPNoDelay(), getBufferSize() or getNumRequestHandlers() is called anywhere in the org.forgerock.opendj.reactive package.

Property Legacy handler LDAPConnectionHandler2
use-tcp-keep-alive socket().setKeepAlive(...) on every accepted channel (LDAPConnectionHandler.java, line 1069) not read; GrizzlyUtils.configureConnection applies the SDK option SO_KEEPALIVE, default true (system property org.forgerock.opendj.io.keepAlive)
use-tcp-no-delay socket().setTcpNoDelay(...) (line 1070) not read; SDK option TCP_NO_DELAY, default true (system property org.forgerock.opendj.io.tcpNoDelay)
buffer-size sizes the per-connection buffer (LDAPClientConnection.java, lines 478-482) not read
num-request-handlers number of request-handler threads (LDAPConnectionHandler.java, line 619) not read; connections are served by the Grizzly selector threads of the shared ServerTCPNIOTransport, sized by the JVM-wide system property org.forgerock.opendj.transport.selectors
allow-tcp-reuse-address setReuseAddress(...) on the listening channel (line 1044) and the "address in use" pre-check only the pre-check (LDAPConnectionHandler2.java, lines 503, 527 and 611-614); the listening socket is bound by the shared transport, whose SO_REUSEADDR is enabled by default and can only be changed JVM-wide with org.forgerock.opendj.transport.reuseAddress (ServerTCPNIOTransport.java, lines 94-99)

Impact

  • use-tcp-keep-alive:false or use-tcp-no-delay:false has no effect on the default listeners: accepted sockets always get SO_KEEPALIVE and TCP_NODELAY switched on.
  • num-request-handlers is marked component-restart, yet restarting the handler changes nothing; the thread count can only be changed for the whole JVM.
  • buffer-size changes are silently dropped.
  • allow-tcp-reuse-address:false makes the pre-check stricter, but the listening socket is still bound with SO_REUSEADDR.
  • Once dsconfig create-connection-handler --type ldap creates the legacy LDAPConnectionHandler, not the LDAPConnectionHandler2 the server ships with #1116 is fixed, dsconfig create-connection-handler --type ldap will also create handlers on LDAPConnectionHandler2, so the gap reaches every LDAP handler an administrator creates, not only the shipped ones.

Steps to reproduce

dsconfig set-connection-handler-prop --handler-name "LDAP Connection Handler" \
  --set use-tcp-no-delay:false --set use-tcp-keep-alive:false \
  -h localhost -p 4444 -D "cn=Directory Manager" -w password -X -n
# restart the handler (or the server), open an LDAP connection and inspect the accepted socket,
# e.g. with `ss -tnoi` on Linux: the keepalive timer is still present

Expected: the accepted socket has SO_KEEPALIVE and TCP_NODELAY switched off, as on a handler running the legacy class.

Proposal

  • use-tcp-keep-alive and use-tcp-no-delay: pass them to the listener as LDAPListener.SO_KEEPALIVE and LDAPListener.TCP_NO_DELAY. LDAPServerFilter already applies the listener options to every accepted connection through GrizzlyUtils.configureConnection, so no change in the SDK is needed.
  • buffer-size, num-request-handlers and the bind side of allow-tcp-reuse-address have no per-handler counterpart in the reactive stack: the transport and its selector threads are shared by every listener in the JVM. Either give them a meaning in LDAPConnectionHandler2, or state in the property descriptions of LDAPConnectionHandlerConfiguration.xml / Package.xml that LDAPConnectionHandler2 ignores them and name the system property that does the job. Which of the two is a decision for the fix.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugjavaChanges to Java sourcesprotocolLDAP protocol extensions, controls and RFC support

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions