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

Partial ack TSO after retransmission + Fix TCP segments order in RTO after fast retransmission #177

Merged
merged 2 commits into from
Aug 21, 2024

Conversation

iftahl
Copy link
Collaborator

@iftahl iftahl commented Jul 4, 2024

  1. Fix ACK of partial TSO segment:
    In the happy TSO path whenever we get an ack, we go over
    the unacked list and shrink TSO segments accordingly.
    The issue is when we get the ack after retransmission where
    the segment/s move from the unacked list to unsent.
    In this case, we don't shrink segments in the unsent list.
    a. Shrink is done for all segments now, not only TSO
    b. Avoid the corner case when partially ACKed and not shrunk segments block TCP progress.

  2. Fix unsent queue after fast retransmission+RTO:
    In fast retransmission, we move a single segment from the unacked list to the unsent list.
    But if we have RTO right after, we move all the unacked list to the unsent list, but we don't
    take into consideration the we might have a retransmitted segment already in the unsent list.

    Example:
    unacked: 1->2->3
    unsent: 4->5->6

    After fast retransmission reorder in LWIP:
    unacked: 2->3
    unsent: 1->4->5->6

    After RTO:
    unacked: ----
    unsent: 2->3->1->4->5->6

Change type

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • CI related changes
  • Documentation content changes
  • Tests
  • Other

Check list

  • Code follows the style de facto guidelines of this project
  • Comments have been inserted in hard to understand places
  • Documentation has been updated (if necessary)
  • Test has been added (if possible)

@iftahl iftahl added bug Something isn't working draft Not to review yet labels Jul 4, 2024
@iftahl iftahl removed the draft Not to review yet label Jul 10, 2024
@iftahl iftahl requested a review from pasis July 10, 2024 12:27
@iftahl iftahl changed the title Rexmit lwip Partial ack TSO after retransmission + Fix TCP segments order in RTO after fast retransmission Jul 31, 2024
@iftahl
Copy link
Collaborator Author

iftahl commented Jul 31, 2024

bot:retest

1 similar comment
@iftahl
Copy link
Collaborator Author

iftahl commented Jul 31, 2024

bot:retest

@@ -1161,276 +1161,6 @@ static void tcp_tso_segment(struct tcp_pcb *pcb, struct tcp_seg *seg, u32_t wnd)
return;
}

static struct tcp_seg *tcp_split_one_segment(struct tcp_pcb *pcb, struct tcp_seg *seg,
Copy link
Member

Choose a reason for hiding this comment

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

[note] #199 contains duplicate of removing unused code. The PR, which is merged second, need to remove the duplicate commit.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done.

@@ -947,6 +940,32 @@ static u32_t tcp_shrink_zc_segment(struct tcp_pcb *pcb, struct tcp_seg *seg, u32
return count;
}

void ack_partial_or_whole_segment(struct tcp_pcb *pcb, u32_t ackno, struct tcp_seg **seg)
Copy link
Member

Choose a reason for hiding this comment

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

Looks like this function can be static.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done.

Comment on lines 1890 to 1906
unacked: 1->2->3
unsent: 4->5->6

After fast retransmission of seg 1,2:
unacked: 3
unsent: 1->2->4->5->6

After RTO without handling correct order:
unacked: ----
unsent: 3->1->2->4->5->6

Therefore - we first move back retransmitted segments to unacked:
unacked: 1->2->3
unsent: 4->5->6
And then move all unacked to unsent:
unacked: ----
unsent: 1->2->3->4->5->6
Copy link
Member

Choose a reason for hiding this comment

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

No need to keep a long comment. It's enough to mention that "fast retransmission can insert out of order segment to the unsent queue".

Also fix the commit message : after a single fast retransmission the context will be:
unacked: 2->3
unsent:: 1->4->5->6
There is no straightforward way to get 1->2->4->5->6

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done.

Comment on lines 1909 to 1676
if (pcb->unsent != NULL && TCP_SEQ_GT(pcb->unacked->seqno, pcb->unsent->seqno)) {
// Move retransmitted segments to unacked
struct tcp_seg *orig_unsent = pcb->unsent;
struct tcp_seg *last_unsent_move_to_unacked = pcb->unsent;
while (last_unsent_move_to_unacked->next != NULL &&
TCP_SEQ_GT(pcb->unacked->seqno, last_unsent_move_to_unacked->next->seqno)) {
last_unsent_move_to_unacked = last_unsent_move_to_unacked->next;
}

pcb->unsent = last_unsent_move_to_unacked->next;
if (pcb->unsent == NULL) {
pcb->last_unsent = NULL;
}

last_unsent_move_to_unacked->next = pcb->unacked;
pcb->unacked = orig_unsent;
}
Copy link
Member

Choose a reason for hiding this comment

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

Is it guaranteed that the retransmitted segments in the unsent are in order? If there is a way to call fast retransmission twice, the order would be reversed. So, either each retransmitted segment needs to be inserted to the right place individually or only the single head element needs to be moved.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It's working properly.

if (pcb->unsent != NULL && TCP_SEQ_GT(pcb->unacked->seqno, pcb->unsent->seqno)) {
// Move retransmitted segments to unacked
struct tcp_seg *orig_unsent = pcb->unsent;
struct tcp_seg *last_unsent_move_to_unacked = pcb->unsent;
Copy link
Member

Choose a reason for hiding this comment

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

Long variable names can complicate code. For short code blocks it's better to keep short names .

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done.

@iftahl iftahl force-pushed the rexmit_lwip branch 2 times, most recently from 6b41015 to 6320417 Compare August 8, 2024 13:49
Copy link
Member

@pasis pasis left a comment

Choose a reason for hiding this comment

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

I'd suggest to update commit message for the shrink commit:

  1. Mention that shrink is done for all segments now, not only TSO
  2. Mention that the patch avoids the corner case when a partially ACKed and not shrunk segments blocks TCP progress.

@AlexanderGrissik
Copy link
Collaborator

bot:retest

@iftahl iftahl force-pushed the rexmit_lwip branch 2 times, most recently from ddad3af to edeccd2 Compare August 13, 2024 07:46
@dpressle
Copy link
Collaborator

bot:retest

1 similar comment
@AlexanderGrissik
Copy link
Collaborator

bot:retest

In the happy TSO path whenever we get an ack, we go over
the unacked list and shrink TSO segments accordingly.
The issue is when we get the ack after retransmission where
the segment/s move from the unacked list to unsent.
In this case, we don't shrink segments in the unsent list.

The change:
1. Shrink every segment and not only TSO segments.
2. Avoid the corner case when a partially ACKed and not shrunk segments block TCP progress.

Signed-off-by: Iftah Levi <iftahl@nvidia.com>
In fast retransmission, we move a single segment from the unacked list to the unsent list.
But if we have RTO right after, we move all the unacked list to the unsent list, but we don't
take into consideration the we might have a retransmitted segment already in the unsent list.

Example:
unacked: 1->2->3
unsent: 4->5->6

After fast retransmission (segments 1 and 2) reorder in LWIP:
unacked: 3
unsent: 1->2->4->5->6

After RTO:
unacked: ----
unsent: 3->1->2->4->5->6

Signed-off-by: Iftah Levi <iftahl@nvidia.com>
@AlexanderGrissik AlexanderGrissik merged commit a6b571f into Mellanox:vNext Aug 21, 2024
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants