Skip to content

Proposal: Back-pressure on opening new streams on yamux #471

@thomaseizinger

Description

@thomaseizinger

Yamux does not offer any form of control in how many streams can be opened by a remote.

This has been an annoyance for a while and transports like QUIC are useful because they do support managing the number of open streams.

I'd like to propose what I believe is a backwards-compatible extension of the yamux spec that gives us some amount of back-pressure for streams.

The yamux specification states for opening of a new stream:

To open a stream, an initial data or window update frame is sent with a new StreamID. The SYN flag should be set to signal a new stream.
The receiver must then reply with either a data or window update frame with the StreamID along with the ACK flag to accept the stream or with the RST flag to reject the stream.

My proposal is as follows:

Implementations SHOULD keep track of how many streams are pending, i.e. they have not yet received an ACK for this stream. When receiving RST for a pending stream, implementations SHOULD take note of the number of currently pending streams as a "pending stream budget". For the remainder of the connection, implementations SHOULD NOT exceed this budget.
Implementations MUST NOT assume for this budget to be a constant but shrink it in case the remote peer keeps sending RST flags for pending streams.

I think this is backwards-compatible because existing implementations already need to handle receiving RST for a stream at any point. What we are doing here is adding meaning to receiving RST whilst we have several pending substreams. This allows us to implement a bounded buffer on the receiver side where any streams exceeding that buffer will send a RST and be dropped. This means we will have 1 failed stream per physical connection that allows us to learn the other party's buffer size.

cc @mxinden @marten-seemann @rkuhn

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions