-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[API Proposal]: Additional QuicConnectionOptions #72984
Comments
Tagging subscribers to this area: @dotnet/ncl Issue DetailsBackground and motivationmsquic has a lot of connection options and S.N.Q exposes just a few List of msquic settings - https://github.com/microsoft/msquic/blob/main/docs/Settings.md Settings I think should be added:
I don't think any of these are necessary for .NET 7. API Proposalnamespace System.Net.Quic
{
public abstract class QuicConnectionOptions
{
public TimeSpan DisconnectTimeout { get; set; }
public int InitialConnectionWindowSize { get; set; }
public int InitialStreamWindowSize { get; set; }
public TimeSpan KeepAliveInterval { get; set; }
public bool DatagramReceiveEnabled { get; set; }
public TimeSpan HandshakeTimeout { get; set; }
}
} API Usagevar quicListenerOptions = new QuicListenerOptions
{
ApplicationProtocols = _tlsConnectionCallbackOptions.ApplicationProtocols,
ListenEndPoint = listenEndPoint,
ListenBacklog = options.Backlog,
ConnectionOptionsCallback = async (connection, helloInfo, cancellationToken) =>
{
var connectionOptions = new QuicServerConnectionOptions
{
// ... set various properties for server connection ...
};
return connectionOptions;
}
}; Alternative DesignsNo response RisksNo response
|
All proposed options seem to be supported by MsQuic Note that |
That seems reasonable, but given it's not critical for 7.0, I'll put it to Future for now |
Triage: we should revisit this in 8.0. We should check usefulness of the parameters and whether they make sense outside of msquic context, e.g. are they transport parameters from the spec? |
Tagging subscribers to this area: @dotnet/ncl Issue DetailsBackground and motivationmsquic has a lot of connection options and S.N.Q exposes just a few List of msquic settings - https://github.com/microsoft/msquic/blob/main/docs/Settings.md Settings I think should be added:
I don't think any of these are necessary for .NET 7. API Proposalnamespace System.Net.Quic
{
public abstract class QuicConnectionOptions
{
public TimeSpan DisconnectTimeout { get; set; }
public int InitialConnectionWindowSize { get; set; }
public int InitialStreamWindowSize { get; set; }
public TimeSpan KeepAliveInterval { get; set; }
public bool DatagramReceiveEnabled { get; set; }
public TimeSpan HandshakeTimeout { get; set; }
}
} API Usagevar quicListenerOptions = new QuicListenerOptions
{
ApplicationProtocols = _tlsConnectionCallbackOptions.ApplicationProtocols,
ListenEndPoint = listenEndPoint,
ListenBacklog = options.Backlog,
ConnectionOptionsCallback = async (connection, helloInfo, cancellationToken) =>
{
var connectionOptions = new QuicServerConnectionOptions
{
// ... set various properties for server connection ...
};
return connectionOptions;
}
}; Alternative DesignsNo response RisksNo response
|
Looking at the options more closely, with optics that we don't want to necessarily get locked to MsQuic and expose only options which will not prevent us to switch implementations in the future. DisconnectTimeoutset in millisecond resolution, default value 16000ms. Does not map to a transport parameter, nor does RFC require this to be app-configurable. This setting seems to be specific to MsQuic. KeepAliveIntervaldisabled by default, set in millisecond resolution. RFC specifies that "An implementation of QUIC might provide applications with an option to defer an idle timeout." but does not specify the form. The other way to do that is providing a method which elicits sending ping manually (as Cloudflare's quiche does). InitialConnectionWindowSizeThis one is a bit tricky. There is The other option is the InitialStreamWindowSizeMsQuic option however, QUIC as a protocol allows setting separate flow-control limits for unidirectional/bidirectional streams (and in bidirectional streams, separate values for the streams initiated locally and remotely). MsQuic just happens to use the same value for all 3 streams. This maps to RFC requires both connection-wide and stream-level control flow limits to be app-configurable. HandshakeIdleTimeoutSet in millisecond resolution, the default value is 10s. This seems to be MsQuic-specific as I can't find anything about separate timeout for handshake in the RFC. DatagramReceiveEnabledto be left out from this proposal, it needs a separate API proposal which includes methods for actually sending/receiving datagrams (#53533) |
We discussed this with the team, and we looked at other implementations to make sure we don't expose something that is not provided by other QUIC implementations if we ever decide to switch or provide option to use different implementation than MsQuic. We found that all implementations expose similar configurations options except the |
Filed microsoft/msquic#3897 for separate options for stream-level flow control |
Updated propsal based on discussion within the team. We have consensus on current proposal. |
namespace System.Net.Quic
{
public struct QuicReceiveWindowSizes
{
/// <summary>
/// The initial flow-control window size for the connection.
/// </summary>
public int Connection { get; set; } = 16 * 1024 * 1024;
/// <summary>
/// The initial flow-control window size for locally initiated bidirectional streams.
/// </summary>
public int LocallyInitiatedBidirectionalStream { get; set; } = 64 * 1024;
/// <summary>
/// The initial flow-control window size for remotely initiated bidirectional streams.
/// </summary>
public int RemotelyInitiatedBidirectionalStream { get; set; } = 64 * 1024;
/// <summary>
/// The initial flow-control window size for (remotely initiated) unidirectional streams.
/// </summary>
public int UnidirectionalStream { get; set; } = 64 * 1024;
}
public partial class QuicConnectionOptions
{
/// <summary>
/// The interval at which keep alive packets are sent on the connection.
/// Default <see cref="TimeSpan.Zero"/>, or <see cref="Timeout.InfiniteTimeSpan"> means no keep alive.
/// </summary>
public TimeSpan KeepAliveInterval { get; set; } = TimeSpan.Infinite;
public QuicReceiveWindowSizes InitialReceiveWindowSizes { get; set; }
/// <summary>
/// The upper bound on time when the handshake must complete. If the handshake does not
/// complete in this time, the connection is aborted.
/// </summary>
public TimeSpan HandshakeTimeout { get; set; } = TimeSpan.FromSeconds(10);
}
} |
@bartonjs Defining
Does not compile because Is it okay to change the type to |
Changing it to a class seems fine to me. |
Background and motivation
msquic has a lot of connection options and S.N.Q exposes just a few
List of msquic settings - https://github.com/microsoft/msquic/blob/main/docs/Settings.md
Settings I think should be added:
Disconnect Timeout - Importance discovered as part of QUIC: QuicStream.WaitForWriteCompletionAsync sometimes doesn't complete #71927. People may want to be more or less aggressive with closing unresponsive streamsDatagramReceiveEnabled - Maybe. I think this will be needed for WebTransport datagram support. Does QuicStream have a story for supporting datagram in the future?I don't think any of these are necessary for .NET 7.
API Proposal (edited by @rzikm)
See also discussion about naming below the proposal, we are open for suggestions for better names. Default values were copied from current MsQuic behavior.
Properties
InitialConnectionReceiveWindowSize
,InitialLocallyInitiatedBidirectionalStreamReceiveWindowSize
,InitialRemotelyInitiatedBidirectionalStreamReceiveWindowSize
, andInitialUnidirectionalStreamReceiveWindowSize
have rather long names but we did come up with a better alternative. They map directly to QUIC transport parametersinitial_max_data
,initial_max_stream_data_bidi_local
,initial_max_stream_data_bidi_remote
, andinitial_max_stream_data_uni
respectively. These transport parameters limit the amount of data the peer can send on the connection as a whole and on streams of individual types to prevent the peer from overwhelming the receiver with data. Thus, theInitial*ReceiveWindowSize
part of the name seems appropriate. The rest of the name identifies the type of stream, where "Locally initiated bidirectional stream" and similar are terms used in the QUIC RFC and we should use them to avoid confusion.For comparison, MsQuic uses names such as
StreamRecvWindowBidiLocalDefault
.And will expand the receive window if appropriate.
Parameter definition from RFC
initial_max_data (0x04)
The initial maximum data parameter is an integer value that contains the
initial value for the maximum amount of data that can be sent on the
connection. This is equivalent to sending a MAX_DATA (Section
19.9) for the
connection immediately after completing the handshake.
initial_max_stream_data_bidi_local (0x05)
This parameter is an integer value specifying the initial flow control limit
for locally initiated bidirectional streams. This limit applies to newly
created bidirectional streams opened by the endpoint that sends the
transport parameter. In client transport parameters, this applies to streams
with an identifier with the least significant two bits set to 0x00; in
server transport parameters, this applies to streams with the least
significant two bits set to 0x01.
initial_max_stream_data_bidi_remote (0x06)
This parameter is an integer value specifying the initial flow control limit
for peer-initiated bidirectional streams. This limit applies to newly
created bidirectional streams opened by the endpoint that receives the
transport parameter. In client transport parameters, this applies to streams
with an identifier with the least significant two bits set to 0x01; in
server transport parameters, this applies to streams with the least
significant two bits set to 0x00.
initial_max_stream_data_uni (0x07)
This parameter is an integer value specifying the initial flow control limit
for unidirectional streams. This limit applies to newly created
unidirectional streams opened by the endpoint that receives the transport
parameter. In client transport parameters, this applies to streams with an
identifier with the least significant two bits set to 0x03; in server
transport parameters, this applies to streams with the least significant two
bits set to 0x02.
API Usage
Alternative Designs
To avoid long property names. We can introduce a wrapper type for the initial
connection window sizes. However, the wrapper type must be a class, otherwise
options.InitialReceiveWindowSizes.ConnectionTotal = x
has no effect. We alsodon't see another use for the type.
Risks
The options above are commonly exposed by other QUIC implementations and none of them are too specific as to vendor lock System.Net.Quic to MsQuic only.
The text was updated successfully, but these errors were encountered: