JDK-8244858 : SO_INCOMING_NAPI_ID support
  • Type: CSR
  • Component: core-libs
  • Sub-Component: java.net
  • Priority: P4
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 15
  • Submitted: 2020-05-12
  • Updated: 2020-05-19
  • Resolved: 2020-05-19
Related Reports
CSR :  
Description
Summary
-------------

Add support for the SO_INCOMING_NAPI_ID socket option to jdk.net.ExtendedSocketOptions. The socket option is Linux specific and allows applications to query the NAPI ([New API](https://en.wikipedia.org/wiki/New_API)) ID of the underlying device queue associated with its socket connection and take advantage of the Application Device Queue (ADQ) feature of high performance Network Interface Card (NIC) devices.

Problem
-----------

For a multi-threaded application and/or multi-application environment, network performance for a target application/thread may be impacted as a result of network utilization of another application/thread. Due to sharing of network hardware resources, traffic destined to target application can get blocked behind data of other applications in the same queue thus introducing unpredictable network performance. Isolating the traffic for different applications/threads to different queues by enabling applications to query the NAPI ID of the queue can reduce system interrupts, improve network throughput and minimize latencies and jitter.

Solution
-----------

Modern NIC devices have multiple queues or channels to transmit and receive network packets. System administrators can allocate network resources to an application in a multi-application environment including a set of device queues (number of Tx/RX queue pairs), dedicated for application traffic. Device then assigns the incoming application connections to these set of queues by defined policies such as round robin. The SO_INCOMING_NAPI_ID socket option provides hints to applications to indicate the device queue from the set of assigned queues, to which an incoming socket connection and packets for that connection are directed to.

For a multi-threaded application to take advantage of these dedicated queues, applications needs the ability to query which queue a connection is assigned to, so all socket connections from a specific device queue can be serviced by a single application thread.  Applications then may utilize busy polling to receive and transmit the network packets, minimizing system interrupts and context switches to better align overall system resources to applications. This helps in improved predictability, reduce latency and improve throughput for applications with SO_INCOMING_NAPI_ID support.

       val napi_id  = socketChannel.getOption(ExtendedSocketOptions.SO_INCOMING_NAPI_ID)
       if (napi_id >= 0) {
          // Assign the channel to the next processor (using incoming napi id)
          // If newConnections queue is full on, block until the space is avaiable
          val processor = synchronized {
              // adjust the index (if necessary) and retrieve the processor atomically for
              // correct behavior in case the number of processors is reduced dynamically
              currentProcessorIndex = napi_id % processors.length
              processors(currentProcessorIndex)
          }
          assignNewConnection(socketChannel, processor, true)
       } else {
           ...
       }

Specification
-----------------

jdk.net: jdk.net.ExtendedSocketOptions 
```
/**
 * Identifies the receive queue that the last incoming packet for the socket
 * was received on.
 *
 * <p> The value of this socket option is a positive {@code Integer} that
 * identifies a receive queue that the application can use to split the
 * incoming flows among threads based on the queue identifier. The value is
 * {@code 0} when the socket is not bound, a packet has not been received,
 * or more generally, when there is no receive queue to identify.
 * The socket option is supported by both stream-oriented and datagram-oriented
 * sockets.
 *
 * <p> The socket option is read-only and an attempt to set the socket option
 * will throw {@code SocketException}.
 *
 * @apiNote
 * Network devices may have multiple queues or channels to transmit and receive
 * network packets. The {@code SO_INCOMING_NAPI_ID} socket option provides a hint
 * to the application to indicate the receive queue on which an incoming socket
 * connection or packets for that connection are directed to. An application may
 * take advantage of this by handling all socket connections assigned to a
 * specific queue on one thread.
 *
 * @since 15
 */
public static final SocketOption<Integer> SO_INCOMING_NAPI_ID = ...
```

Additional links
--------------------
javadoc: http://cr.openjdk.java.net/~sviswanathan/Vladimir/8244858/ExtendedSocketOptions.html

Comments
Moving to Approved.
19-05-2020

This is a JDK and Linux specific socket option that targets very advanced developers, it's not a socket option that most developers will ever see. The javadoc that has been agreed on net-dev is at the same level of the docs for both standard and other extended socket options. Additional documentation, or examples, will be required for developers to make proper use of this socket option.
17-05-2020

Moving to Provisional. Please have one or more networking engineers review the request before finalizing it for the second round of CSR review.
15-05-2020