Skip to content

TCP Fast Open implementation? #1476

Open
@icylogic

Description

@icylogic

Proposal: TCP Fast Open

TCP Fast Open is an extension for TCP to speed up the handshaking process in successive TCP connections. This feature has been available for OSX and Linux for years and was implemented on Windows by Anniversary Update. Users could check by netsh

>netsh int tcp show global
Querying active state...

TCP Global Parameters
----------------------------------------------
...
TCP Fast Open                       : enabled

but dotnet has not implemented this for System.Net yet.

Rational and Usage

This new API is important and powerful because when it is used with TLS False Start, we are down to 1-RTT from original 3-RTT for a successive TCP+TLS (HTTPS) connection, and furthermore, 0-RTT could be achieved by combining TFO and TLS 1.3.

And it's easy to use: programmers only need to add a few lines to set an socket option and provide a buffer filled with data to send. Here's the usage:

var s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
var e = new SocketAsyncEventArgs();
s.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.FastOpen, true);
e.SetBuffer(buffer, offset, length); 
s.ConnectAsync(e);

Note that buffer[offset] ~ buffer[offset+length-1] might be (partially) sent together with SYN. It's up to the OS how to send.

A typical usage is the TLS handshake. In successive connections, the client could send a SYN with TLS Client Hello.

Please check the "Original Proposal" for details.

Proposed API

namespace System.Net.Sockets
{
    // Defines socket option names for the <see cref='System.Net.Sockets.Socket'/> class.
    public enum SocketOptionName
    {
        // ...

        #region SocketOptionLevel.Tcp
        // ...
        FastOpen = 15
        #endregion

    }
}

This enum value is 15 for Windows according to ws2ipdef.h.

Problems & Extra works

  • Implementation
    In fact, adding just one line like the code above in SocketOptionName.cs would work for Windows.
    However, it might not work for Unix. Since dotnet simply pass the socket option to native API on Windows while the Unix Pal would check the value. For more information about the difference please check the relevant issue dotnet/corefx#14237 . To make this work for Unix we may need to modify this part

  • Compatibility
    According to MSDN, this option is available since Windows 10, 1607. Maybe we should generate a warning if this option is set on the older Windows platform

  • Other System.Net API
    For API using sockets in its code such as WebClient or HttpClient, it could take advantage of this feature, especially for "https://" scheme.

Original Proposal

TCP Fast Open on Windows

Windows has introduced TCP Fast Open in the Anniversary Update serveral months ago. (Announcing: New Transport Advancements in the Anniversary Update for Windows 10 and Windows Server 2016)

TFO is one full Round Trip Time (RTT) faster than the standard TCP setup which requires a three way-handshake. This leads to latency savings and is very relevant to short web transfers over the Internet where the average latency is on the order of 40 msec.

Native API for TCP Fast Open

This feature could be turned on using native Windows Socket 2 API: IPPROTO_TCP Socket Options. But it has not been implemented in dotnet (SocketOptionName.cs).

dotnet API relating to TCP Fast Open

According to the Native API Documentation, in addition to passing a new enum value to the method setSocketOption which then calls the native setsockopt, we need to set up the buffer including the data to send during the initial connection:

Note that to make use of fast opens, you should use ConnectEx to make the initial connection, and specify data in that function's lpSendBuffer parameter to be transferred during the handshake process. Some of the data in lpSendBuffer will be transferred under the Fast Open protocol.

The native method ConnectEx is called by DoOperationConnect which is called by socket.ConnectAsync on Windows. And the buffer could be set as a property of SocketAsyncEventArgs.

//TFO is defined as 15 in ws2ipdef.h
socket.SetSocketOption(SocketOptionLevel.Tcp, (SocketOptionName)15, true);  
e.SetBuffer(buffer, start, length);  //e is a SocketAsyncEventArgs
socket.ConnectAsync(e);

dotnet implementation

The most straightforward way to implement this feature is to add a new value to the SocketOptionName enum. But it enables this feature only on Windows. In this issue https://github.com/dotnet/corefx/issues/14237, it seems that members are interested in introducing a new cross-platform API for TCP options.

It would be nice if the Public API contained all of the possible socket options across Windows, Linux, and Darwin.

PS. TCP Fast Open is natively supported on Linux and OSX. Here's how to use it on Linux: TCP Fast Open: expediting web services

More about TCP Fast Open:

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions