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

Resend uTP ACKs that fail to send due to stalling #7113

Merged
merged 1 commit into from
Sep 28, 2022
Merged

Resend uTP ACKs that fail to send due to stalling #7113

merged 1 commit into from
Sep 28, 2022

Conversation

thrnz
Copy link
Contributor

@thrnz thrnz commented Sep 27, 2022

Following #7107, uTP packets with payload that failed to send due to a stalled socket should now be sent once the socket becomes writable again. However, this doesn't apply to ST_STATE packets (ie payload-less ACKs), which would simply be lost. If another packet isn't sent out in time (updating our ack_nr at the other end) then this will be seen as loss and can trigger a needless resend by the other-end.

The idea behind this change is to note that an ack is still needed if the socket stalls while sending an empty payload ACK-only packet. Once the socket is writable again, the deferred ack is then sent out if its still needed.

I wonder if a simulation with a low enough send_socket_buffer_size might be able to trigger this and to confirm that this fix as well as #7107 work as intended.

@arvidn
Copy link
Owner

arvidn commented Sep 27, 2022

I've added it to my list to add a new uTP simulation where the send socket buffer is filled up. I'm not sure the current libsimulator models this yet.

Copy link
Owner

@arvidn arvidn left a comment

Choose a reason for hiding this comment

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

looks good. just some thoughts

// if the socket stalled while sending an ack, then send it
// now if needed
if (m_deferred_ack && !m_stalled)
send_ack();
Copy link
Owner

Choose a reason for hiding this comment

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

maybe I'm misunderstanding something here. but if the send_pkt()-loop above ended up sending any packets, we don't need to send a dedicated ACK packet. Since the ACK sequence number is always included in the header.

I would have expected this part of the patch to instead do something like: if m_deferred_ack is set, make the first call to send_pkt() be called with the pkt_ack flag. If it returns true, then move on to run the loop that attempts to drain the send buffer.

looking closer i see that m_deferred_ack is actually cleared by send_pkt() if it ends up sending a packet, so I suppose this also works. However, if send_pkt() doesn't send any packets (and doesn't clear m_deferred_ack), there shouldn't be a way for m_stalled to have been set either.

I'm leaning towards thinking that this code might be slightly simpler if it doesn't rely onm_deferred_ack and m_stalled being updated by the call to send_pkt().

src/utp_stream.cpp Outdated Show resolved Hide resolved
Comment on lines +965 to +968
// if the socket stalled while sending an ack then there will be a
// pending deferred ack. make sure it gets sent out
if (!m_deferred_ack || send_pkt(pkt_ack))
while(send_pkt());
Copy link
Contributor Author

Choose a reason for hiding this comment

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

How about this: If there's no outstanding unsent ack then go straight to the send_pkt() loop like normal, otherwise use the pkt_ack flag for the first call, then proceed into the loop if needed. It's much simpler, and I think will achieve the same thing.

Copy link
Owner

Choose a reason for hiding this comment

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

that sounds good

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