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

Correct/Simplify the Ack algorithm #177

Merged
merged 23 commits into from
Apr 30, 2019

Conversation

jstnlef
Copy link
Contributor

@jstnlef jstnlef commented Apr 22, 2019

Honestly, I have a lot more tests to write before this goes out the door but I wanted to get some initial feedback on what I have currently.

Key highlights are -

  1. I rewrote the sequence buffer to handle some cases we were explicitly not handling before. For example, if a sequence number is too old, we need to ensure that we don't place it into the buffer. Also, the perfectly valid sequence number u16::max was being used as a "null" value which means that we would have incorrect behavior.
  2. I redid the ack-ing code to be a bit simpler and easy to follow.
  3. I am now no longer counting packets as dropped until we haven't received an ack for those packets in 32+ sequence numbers.

I also added some descriptive comments around why I'm calculating the fields as I am.

@jstnlef jstnlef requested review from fhaynes and TimonPost April 22, 2019 07:38
Copy link
Owner

@TimonPost TimonPost 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, I like how this is evolving and I am curious for the tests.

@jstnlef jstnlef force-pushed the correct-ack-algorithm branch 2 times, most recently from 1a1d465 to 1424690 Compare April 26, 2019 03:22
/// Returns the ack_bitfield corresponding to which of the past 32 packets we've
/// successfully received.
pub fn ack_bitfield(&self) -> u32 {
let most_recent_remote_seq_num: u16 = self.remote_sequence_num().wrapping_sub(1);
Copy link
Owner

Choose a reason for hiding this comment

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

last_remote_seq_num?

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 wanted to make this more specific in that it should be the sequence number that is furthest ahead rather than the last one we've received.

}

// TODO: Is this what we want?
// assert_eq!(handler.dropped_packets.len(), 25);
Copy link
Owner

Choose a reason for hiding this comment

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

I think this is exactly what we want if we have 100 packets and we divide that by 4 we will get 25. So we should have 25 dropped packets over 100 packets. If you don't trust the modulo operation please try the following code out:

let mut counter = 1;
        for i in 0..100 {
            handler.process_outgoing(vec![1, 2, 3].as_slice(), OrderingGuarantee::None);
            handler.sequence_number = i;

            // dropping every 4th with modulo's
            if counter == 4 {
                println!("Dropping packet: {}", drop_count);
                drop_count += 1;

                counter = 1;
            } else {
                // We send them a packet
                other.process_incoming(i, handler.remote_sequence_num(), handler.ack_bitfield());
                // Skipped: other.process_outgoing
                // And it makes it back
                handler.process_incoming(i, other.remote_sequence_num(), other.ack_bitfield());

                counter += 1;
            }
        }

This will drop every fourth packet for sure.

Copy link
Contributor Author

@jstnlef jstnlef Apr 26, 2019

Choose a reason for hiding this comment

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

This goes back to the discussion we were having the other day on discord (plus I know how modulo works :P). The reason why we would only get 17 dropped packets in this case is that the algorithm waits until it sees 32 packets that haven't acked that sequence number. So at received packet 100, which is the last packet received from the remote host, we have an ack field which looks like 01110111011101110111011101110111. <- This is where those extra 8 packets are. We haven't yet determined that they have been dropped because they haven't "fallen off the end"

@TimonPost
Copy link
Owner

The original acking code has some nice tests by the way which you could use as a reference for this implementation.

@codecov
Copy link

codecov bot commented Apr 29, 2019

Codecov Report

Merging #177 into master will decrease coverage by 0.18%.
The diff coverage is 99.01%.

Impacted file tree graph

@@            Coverage Diff            @@
##           master    #177      +/-   ##
=========================================
- Coverage   97.68%   97.5%   -0.19%     
=========================================
  Files          27      25       -2     
  Lines        2071    2000      -71     
=========================================
- Hits         2023    1950      -73     
- Misses         48      50       +2
Impacted Files Coverage Δ
src/packet/enums.rs 93.44% <ø> (ø) ⬆️
src/net/quality.rs 97.91% <ø> (ø) ⬆️
src/net/socket.rs 97.34% <100%> (ø) ⬆️
src/infrastructure/congestion.rs 100% <100%> (ø) ⬆️
src/net/virtual_connection.rs 96.66% <100%> (ø) ⬆️
src/config.rs 100% <100%> (ø) ⬆️
src/infrastructure/fragmenter.rs 92.3% <100%> (+0.12%) ⬆️
src/packet/outgoing.rs 98.59% <100%> (ø) ⬆️
src/packet/packet_reader.rs 96.35% <100%> (ø) ⬆️
src/sequence_buffer.rs 98.48% <98.48%> (ø)
... and 3 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 690af4f...6b9c9ac. Read the comment docs.

@jstnlef jstnlef force-pushed the correct-ack-algorithm branch from bc4d165 to b5f1fe6 Compare April 29, 2019 03:13
@jstnlef jstnlef changed the title WIP - Correct/Simplify the Ack algorithm Correct/Simplify the Ack algorithm Apr 29, 2019
@jstnlef
Copy link
Contributor Author

jstnlef commented Apr 29, 2019

I feel pretty good about this at this point. Would like to see what you guys think.

Copy link
Owner

@TimonPost TimonPost left a comment

Choose a reason for hiding this comment

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

This is awesome work!

I have one comment which you can ignore or try to implement:

Can we somehow optimize the collecting of dropped packets?

We could, for example, return a lazy loader here, instead of collecting, and do the same over here and then continue this lazy operator here. I think that this could improve the code. What do you think, Is it worth it?

@jstnlef
Copy link
Contributor Author

jstnlef commented Apr 29, 2019

Not a bad idea. I'll see what I can do tonight 👍

@jstnlef
Copy link
Contributor Author

jstnlef commented Apr 30, 2019

Hrm. I think it would take a bit to get this set up as a lazy iterator. We can take it as a future improvement I think 👍

@TimonPost
Copy link
Owner

Right, let's get this merged and create an issue for it.

@jstnlef jstnlef merged commit c5c9173 into TimonPost:master Apr 30, 2019
@jstnlef
Copy link
Contributor Author

jstnlef commented Apr 30, 2019

Ticket here: #182

@jstnlef jstnlef deleted the correct-ack-algorithm branch May 6, 2019 05:40
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