Skip to content

Conversation

vlad9486
Copy link
Contributor

No description provided.

@vlad9486 vlad9486 force-pushed the fix/yamux-backpressure branch 3 times, most recently from 02a5f15 to 2f6a516 Compare October 17, 2024 11:10
@vlad9486 vlad9486 force-pushed the fix/yamux-backpressure branch from 2f6a516 to 7a942be Compare October 17, 2024 11:15
@vlad9486 vlad9486 requested a review from tizoc October 17, 2024 11:15
use std::ops::Sub;

if let YamuxFrameInner::Data(data) = &mut self.inner {
if data.len() == pos {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe here should be if data.len() <= pos

@vlad9486 vlad9486 requested review from 0xMimir and dkuehr October 17, 2024 11:27
.update_window(false, difference);
.or_insert_with(YamuxStreamState::incoming);
stream.update_window(false, difference);
if difference > 0 {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this can be 0 or negative? in which cases does that happen?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my implementation it is signed, but in go implementation it is unsigned, so the window could only grow. So, this is just sanity check, maybe redundant. Peer cannot harm us by making its own window too big.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, please add a bug_condition! call in the else branch so that if this ever happens for some reason we will know about it. That is something we want to do in general, to avoid such unexpected (unenforced) cases happening silently without us noticing

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I add a runtime error, not bug_condition, because peer can send us this and we should not crash.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right, this is based on external input, so it is not exactly a bug_condition!. Btw bug_condition only panics if a flag is enabled in the environment, otherwise it just logs an error (but again this specific case is not for it)

Copy link
Contributor

@dkuehr dkuehr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a more detailed description of the problem(s) this PR solves.
Also, it would be nice to do some testing of if with our p2p fuzzer since the change is not trivial.

}
}
YamuxFrameInner::WindowUpdate { .. } => {
while let Some(frame) = pending_outgoing.pop_front() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any bound or practical limit in how many elements we can have in pending_outgoing?
I'm concerned that someone could try to fill the dispatch queue and and cause blockings in the state machine

pub writable: bool,
pub window_theirs: u32,
pub window_ours: u32,
pub pending: VecDeque<YamuxFrame>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should make this bounded

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I missed this

// either the window cannot accept any byte,
// or the queue is already not empty
// in both cases the whole frame goes in the queue and nothing to send
stream.pending.push_back(frame);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to add a limit here. Malicious peer can keep its window small and send an RPC request in a loop.

@vlad9486
Copy link
Contributor Author

@dkuehr
Without this change, our implementation doesn't respect the yamux protocol. It sends the peer more than the peer allows to send. This doesn't cause a real problem, because the OCaml node doesn't penalise us for this. But Juraj wants us to use this yamux limit in the future to prioritise block production over other tasks (bootstrap and kademlia) and to support slow hardware (raspberry pi). So it will be necessary that our implementation respects it.

@vlad9486 vlad9486 force-pushed the fix/yamux-backpressure branch from 8b5fd33 to e54fb26 Compare October 17, 2024 15:05
}
}
YamuxFrameInner::WindowUpdate { difference } => {
if *difference < 0 {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vlad9486 what about 0 ? that case is not covered. The other condition uses > 0 and this one < 0, which means there is no handling for 0

Copy link
Contributor Author

@vlad9486 vlad9486 Oct 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tizoc Yes, initially I wrote <=, but apparently the peer sends window update with zero if it wants to open the stream but not send data, so it sends flag SYN. Of course it could send data with zero length body, but it sends window update.

@vlad9486 vlad9486 merged commit 555bc51 into develop Oct 18, 2024
28 checks passed
@tizoc tizoc deleted the fix/yamux-backpressure branch October 28, 2024 21:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants