1
0
mirror of https://github.com/mfontanini/libtins synced 2026-01-23 02:35:57 +01:00

Properly handle out of order SACKs on AckTracker

This commit is contained in:
Matias Fontanini
2016-04-03 09:39:11 -07:00
parent 8d52d73968
commit d3c576f6de
2 changed files with 45 additions and 3 deletions

View File

@@ -46,6 +46,15 @@ using Tins::Internals::seq_compare;
namespace Tins {
namespace TCPIP {
uint32_t interval_start(const AckedRange::interval_type& interval) {
if (interval.bounds() == interval_bounds::left_open()) {
return interval.lower() + 1;
}
else {
return interval.lower();
}
}
uint32_t interval_end(const AckedRange::interval_type& interval) {
if (interval.bounds() == interval_bounds::right_open()) {
return interval.upper() - 1;
@@ -123,10 +132,21 @@ void AckTracker::process_sack(const vector<uint32_t>& sack) {
// Left edge must be lower than right edge
if (seq_compare(sack[i - 1], sack[i]) < 0) {
AckedRange range(sack[i - 1], sack[i] - 1);
// If this range starts after our current ack number
if (seq_compare(range.first(), ack_number_) > 0) {
// If this range ends after our current ack number
if (seq_compare(range.last(), ack_number_) > 0) {
while (range.has_next()) {
acked_intervals_.insert(range.next());
AckedRange::interval_type next = range.next();
uint32_t start = interval_start(next);
if (seq_compare(start, ack_number_) <= 0) {
// If this interval starts before or at our ACK number
// then we need to update our ACK number to the end of
// this interval
ack_number_ = interval_end(next);
}
else {
// Otherwise, push the interval into the ACK set
acked_intervals_.insert(next);
}
}
}
}

View File

@@ -663,15 +663,19 @@ TEST_F(AckTrackerTest, AckingTcp_Sack2) {
EXPECT_TRUE(tracker.is_segment_acked(maximum - 2, 1));
EXPECT_TRUE(tracker.is_segment_acked(2, 3));
EXPECT_FALSE(tracker.is_segment_acked(maximum - 10, 10));
EXPECT_EQ(maximum - 10, tracker.ack_number());
tracker.process_packet(make_tcp_ack(maximum - 2));
EXPECT_EQ(1U + 10U, tracker.acked_intervals().size());
EXPECT_EQ(maximum - 2, tracker.ack_number());
tracker.process_packet(make_tcp_ack(5));
EXPECT_EQ(4U, tracker.acked_intervals().size());
EXPECT_EQ(5, tracker.ack_number());
tracker.process_packet(make_tcp_ack(15));
EXPECT_EQ(0U, tracker.acked_intervals().size());
EXPECT_EQ(15, tracker.ack_number());
}
TEST_F(AckTrackerTest, AckingTcp_Sack3) {
@@ -682,9 +686,27 @@ TEST_F(AckTrackerTest, AckingTcp_Sack3) {
make_pair(maximum - 3, 5)
));
EXPECT_EQ(9U, tracker.acked_intervals().size());
EXPECT_EQ(maximum - 10, tracker.ack_number());
tracker.process_packet(make_tcp_ack(maximum));
EXPECT_EQ(5U, tracker.acked_intervals().size());
EXPECT_EQ(maximum, tracker.ack_number());
}
TEST_F(AckTrackerTest, AckingTcp_SackOutOfOrder1) {
AckTracker tracker(0, true);
tracker.process_packet(make_tcp_ack(10));
tracker.process_packet(make_tcp_ack(0, make_pair(9, 12)));
EXPECT_EQ(0, tracker.acked_intervals().size());
EXPECT_EQ(11, tracker.ack_number());
}
TEST_F(AckTrackerTest, AckingTcp_SackOutOfOrder2) {
AckTracker tracker(0, true);
tracker.process_packet(make_tcp_ack(10));
tracker.process_packet(make_tcp_ack(0, make_pair(10, 12)));
EXPECT_EQ(0, tracker.acked_intervals().size());
EXPECT_EQ(11, tracker.ack_number());
}
TEST_F(FlowTest, AckNumbersAreCorrect) {