libp2p / jvm-libp2p

a libp2p implementation for the JVM, written in Kotlin 🔥
https://libp2p.io
Apache License 2.0
260 stars 74 forks source link

[Yamux] Allow max ACK backlog of 256 streams #340

Closed StefanBratanov closed 10 months ago

StefanBratanov commented 10 months ago

https://github.com/libp2p/specs/blob/master/yamux/README.md#ack-backlog--backpressure

Implements SHOULD at most allow an ACK backlog of 256 streams.

mxinden commented 10 months ago

//CC @thomaseizinger who pushed a lot for this to land in rust-libp2p and specs.

Nashatyrev commented 10 months ago

Just to make sure I'm getting the Yamux spec correctly:

There could be two kinds of unacknowledged streams:

So the questions:

  1. should we account both types as a sum and treat them equally?
  2. In the case of exceeding unacknowledged streams threshold what should we do when ... opening a new stream locally? Should we throw MuxerWriteException? (i think yes) Should we also abort the connection? (probably no)
  3. In the case of exceeding unacknowledged streams threshold what should we do when ... receiving SYN from remote? Abort the stream (by sending back RST)? Abort the connection?
mxinden commented 10 months ago

should we account both types as a sum and treat them equally?

They should be accounted separately. A should not ACK inbound streams from B, in case A's application layer has not yet read or written to a stream. B should not open a new stream to A in case 256 outbound streams to A have not yet been ACKed. Same vice versa for streams from A to B.

mxinden commented 10 months ago

In the case of exceeding unacknowledged streams threshold what should we do when ... opening a new stream locally? Should we throw MuxerWriteException? (i think yes) Should we also abort the connection? (probably no)

Do you have any way to backpressure the application? In Rust and I am assuming in Go as well, we suspend the green thread.

mxinden commented 10 months ago

In the case of exceeding unacknowledged streams threshold what should we do when ... receiving SYN from remote? Abort the stream (by sending back RST)? Abort the connection?

In rust-yamux today it is best effort only, enforced at the outbound end for now.

https://github.com/libp2p/rust-yamux/blob/93b70626f7f3d83f97951d9cd5c2951500088f0d/yamux/src/connection.rs#L435-L439

In case you want to enforce it at the receiving side, I would consider resetting the stream exceeding the limit.

Nashatyrev commented 10 months ago

Do you have any way to backpressure the application?

Not with the present API

In Rust and I am assuming in Go as well, we suspend the green thread.

Yeah, that's a good solution.

In case you want to enforce it at the receiving side, I would consider resetting the stream exceeding the limit.

If both peers has the same ACK_BACKLOG_ALLOWANCE then this situation should be treated as the protocol violation. Am I getting it right? In that case even connection abort would be appropriate

mxinden commented 10 months ago

In case you want to enforce it at the receiving side, I would consider resetting the stream exceeding the limit.

If both peers has the same ACK_BACKLOG_ALLOWANCE then this situation should be treated as the protocol violation. Am I getting it right?

Correct. Though I am not aware of a single libp2p based network out there today that supports the yamux ack backlog feature across all nodes. Thus treating it as best effort everywhere.

Nashatyrev commented 10 months ago

It also looks like we need to treat initiator/responder acknowledgments separately as per comment from @mxinden

@StefanBratanov are you planning to address this here yet or later? Else the PR looks good to me.

StefanBratanov commented 10 months ago

It also looks like we need to treat initiator/responder acknowledgments separately as per comment from @mxinden

@StefanBratanov are you planning to address this here yet or later? Else the PR looks good to me.

Working on it now. Think it makes sense to be in this PR as well.

StefanBratanov commented 10 months ago

It also looks like we need to treat initiator/responder acknowledgments separately as per comment from @mxinden

@StefanBratanov are you planning to address this here yet or later? Else the PR looks good to me.

Working on it now. Think it makes sense to be in this PR as well.

Done.