Skip to content
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

Change the Nagle algorithm to allow a single undersized packet in flight at a time #7055

Merged
merged 1 commit into from
Sep 9, 2022
Merged

Conversation

thrnz
Copy link
Contributor

@thrnz thrnz commented Sep 8, 2022

Currently, libtorrent will hold back an undersized uTP packet until all previously transmitted packets have been ack'd. This can add an extra RTT of delay when sending the last few bytes of a 'big' send (eg. a stream of data followed by a choke).

This suggested change will only hold back the undersized packet if there is currently an undersized packet in flight, essentially allowing one undersized packet to be sent per RTT. This would allow the tail of a 'big' send to go out immediatley without any extra delay.

This is done by noting the sequence number of the last undersized packet sent, as suggested here

See #6935

if (m_bytes_in_flight > 0
&& int(p->size) < std::min(int(p->allocated), effective_mtu)
&& !force
&& m_nagle)
&& m_nagle
&& !compare_less_wrap(m_nagle_seq_nr, m_acked_seq_nr, ACK_MASK))
Copy link
Owner

Choose a reason for hiding this comment

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

i m_nagle_seq_nr == m_acked_seq_nr, that means we don't have an outstanding undersized packet, right?
I believe this logic handles that case incorrectly. compare_less_wrap() would return false and we would hold off the packet.

If I understand correctly, this last condition should be:

&& compare_less_wrap(m_acked_seq_nr, m_nagle_seq_nr, ACK_MASK))

@@ -1549,11 +1550,12 @@ bool utp_socket_impl::send_pkt(int const flags)
if (m_bytes_in_flight > 0
&& int(p->size) < std::min(int(p->allocated), effective_mtu)
&& !force
&& m_nagle)
&& m_nagle
&& !compare_less_wrap(m_nagle_seq_nr, m_acked_seq_nr, ACK_MASK))
Copy link
Owner

Choose a reason for hiding this comment

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

I believe the comment aboc also applies here

@arvidn
Copy link
Owner

arvidn commented Sep 8, 2022

this is an interesting result of this test: https://github.com/arvidn/libtorrent/runs/8244601393?check_suite_focus=true#step:5:723

If it's not caused by the comparison issue, it would be good to understand where the redundant packet is coming from

@thrnz
Copy link
Contributor Author

thrnz commented Sep 8, 2022

Well spotted. I'll fix that up and see how that effects that unexpected packet.

@thrnz
Copy link
Contributor Author

thrnz commented Sep 8, 2022

Looks like its still there. Might have to do some more digging to work out whats going on.

@arvidn
Copy link
Owner

arvidn commented Sep 8, 2022

the redundant packet counter is incremented on utp_stream.cpp:2367.
We receive a packet that's ACKing a packet that hasn't been sent. The socket is in fin_sent state, and when sending a FIN, the seq_nr is not incremented. So it looks like this is the FIN being acked, but it's ignored as an invalid ack.
The incoming packet is also a FIN.

@arvidn
Copy link
Owner

arvidn commented Sep 8, 2022

I believe this change should be made as well. It's unrelated to your change except that they affect the simulation outcome:

diff --git a/src/utp_stream.cpp b/src/utp_stream.cpp
index 4d142daac..18a134ceb 100644
--- a/src/utp_stream.cpp
+++ b/src/utp_stream.cpp
@@ -2353,7 +2353,7 @@ bool utp_socket_impl::incoming_packet(span<char const> b
        // Note that when we send a FIN, we don't increment m_seq_nr
        std::uint16_t const cmp_seq_nr =
                ((state() == state_t::syn_sent || state() == state_t::fin_sent)
-                       && ph->get_type() == ST_STATE)
+                       && (ph->get_type() == ST_STATE || ph->get_type() == ST_FIN))
                ? m_seq_nr : (m_seq_nr - 1) & ACK_MASK;
 
        if ((state() != state_t::none || ph->get_type() != ST_SYN)

@arvidn
Copy link
Owner

arvidn commented Sep 8, 2022

feel free to incorporate that patch in this PR, or just fix up the test and I can add it afterwards

@thrnz
Copy link
Contributor Author

thrnz commented Sep 9, 2022

feel free to incorporate that patch in this PR, or just fix up the test and I can add it afterwards

Will do.

I'll fix the expected packet counts in test_utp.cpp once #7056 is merged as it will likely effect the results.

@arvidn arvidn merged commit 3060467 into arvidn:RC_2_0 Sep 9, 2022
@thrnz thrnz deleted the nagle-minshall branch October 21, 2022 20:01
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.

2 participants