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

gbn: Sender side only packeting resend bug fix #87

Commits on Dec 1, 2023

  1. gbn: clean up queue init

    ellemouton committed Dec 1, 2023
    Configuration menu
    Copy the full SHA
    c0eea25 View commit details
    Browse the repository at this point in the history

Commits on Jan 8, 2024

  1. gbn: change implication of processNACK signature

    The processNACK function returns two booleans as its signature.
    The first boolean used to only indicate if the NACK was part of the
    queue, but is with this commit expanded to indicate if the queue needs
    to be resent or not as a result of the NACK.
    
    The second boolean indicates if the queue sequence base was bumped or
    not. Previously, the bumped value for processNACK didn't accurately
    reflect if the queue sequence base was actually bumped or not for the
    cases when we didn't trigger a resend. This commit addresses that issue.
    Updating the bumped value to be correct has no real impact on the
    current implementation of the gbn conn, but it might start having an
    effect if the implementation is modified in the future.
    ViktorTigerstrom committed Jan 8, 2024
    Configuration menu
    Copy the full SHA
    6967ad3 View commit details
    Browse the repository at this point in the history
  2. Configuration menu
    Copy the full SHA
    4c3528c View commit details
    Browse the repository at this point in the history
  3. gbn: add syncer struct

    The syncer struct can be used to ensure that both the sender and the
    receiver are in sync before the waitForSync function is completed. This
    ensures that we don't end up in a loop where one party keeps resending
    packets over and over again. This is done by awaiting that we receive
    either the an expected ACK or an expected NACK after resending the
    queue. The expected ACK is the ACK for the last packet that has been
    resent, and the expected NACK is the NACK sequence following the last
    packet that has been resent.
    
    To understand why we need to await the awaited ACK/NACK after resending
    the queue, consider the following scenario:
    
    1.
    Alice sends packets 1, 2, 3 & 4 to Bob.
    2.
    Bob receives packets 1, 2, 3 & 4, and sends back the respective ACKs.
    3.
    Alice receives ACKs for packets 1 & 2, but due to latency the ACKs for
    packets 3 & 4 are delayed and aren't received until Alice resend timeout
    has passed, which leads to Alice resending packets 3 & 4. Alice will
    after that receive the delayed ACKs for packets 3 & 4, but will consider
    that as the ACKs for the resent packets, and not the original packets
    which they were actually sent for. If we didn't wait after resending the
    queue, Alice would then proceed to send more packets (5 & 6).
    4.
    When Bob receives the resent packets 3 & 4, Bob will respond with
    NACK 5. Due to latency, the packets 5 & 6 that Alice sent in step (3)
    above will then be received by Bob, and be processed as the correct
    response to the NACK 5. Bob will after that await packet 7.
    5.
    Alice will receive the NACK 5, and now resend packets 5 & 6. But as Bob
    is now awaiting packet 7, this send will lead to a NACK 7. But due to
    latency, if Alice doesn't wait resending the queue, Alice will proceed
    to send new packet(s) before receiving the NACK 7.
    6.
    This resend loop would continue indefinitely, so we need to ensure that
    Alice waits after she has resent the queue, to ensure that she doesn't
    proceed to send new packets before she is sure that both parties are in
    sync.
    
    To ensure that we are in sync, after we have resent the queue, we will
    await that we either:
    1. Receive a NACK for the sequence number succeeding the last packet in
    the resent queue i.e. in step (3) above, that would be NACK 5.
    OR
    2. Receive an ACK for the last packet in the resent queue i.e. in step
    (3) above, that would be ACK 4. After we receive the expected ACK, we
    will then wait for the duration of the resend timeout before continuing.
    The reason why we wait for the resend timeout before continuing, is that
    the ACKs we are getting after a resend, could be delayed ACKs for the
    original packets we sent, and not ACKs for the resent packets. In step
    (3) above, the ACKs for packets 3 & 4 that Alice received were delayed
    ACKs for the original packets. If Alice would have immediately continued
    to send new packets (5 & 6) after receiving the ACK 4, she would have
    then received the NACK 5 from Bob which was the actual response to the
    resent queue. But as Alice had already continued to send packets 5 & 6
    when receiving the NACK 5, the resend queue response to that NACK would
    cause the resend loop to continue indefinitely.
    
    When either of the 2 conditions above are met, we will consider both
    parties to be in sync, and we can proceed to send new packets.
    ViktorTigerstrom committed Jan 8, 2024
    Configuration menu
    Copy the full SHA
    3b5967f View commit details
    Browse the repository at this point in the history
  4. Configuration menu
    Copy the full SHA
    768ef7a View commit details
    Browse the repository at this point in the history
  5. Configuration menu
    Copy the full SHA
    4a43139 View commit details
    Browse the repository at this point in the history
  6. Configuration menu
    Copy the full SHA
    6f969c9 View commit details
    Browse the repository at this point in the history
  7. Configuration menu
    Copy the full SHA
    77d0bd5 View commit details
    Browse the repository at this point in the history
  8. gbn+mailbox: force connection status change on FIN

    When the client receives+processes a FIN packet, we force the connection
    to status ClientStatusSessionNotFound, as in rare occasions the
    corresponding server may have time to close the connection before we've
    already processed the sent FIN packet by the server. In that case, if we
    didn't force a new status, the client would never mark the connection as
    status ClientStatusSessionNotFound.
    
    This solves a bug for the testServerReconnect itest, as that test would
    sometimes fail due to the FIN packet being processed but without
    changing the connection status, leading to a test predicate never being
    satisfied.
    ViktorTigerstrom committed Jan 8, 2024
    Configuration menu
    Copy the full SHA
    5e16121 View commit details
    Browse the repository at this point in the history