dcsctp: implement handover in DataTracker
Bug: webrtc:13154 Change-Id: Ia8c41dcffd95dafd904ee630f2131b575fe833dd Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/231955 Reviewed-by: Victor Boivie <boivie@webrtc.org> Commit-Queue: Sergey Sukhanov <sergeysu@webrtc.org> Cr-Commit-Position: refs/heads/main@{#34996}
This commit is contained in:
parent
e229fb83fb
commit
225cd47445
@ -32,6 +32,8 @@ struct DcSctpSocketHandoverState {
|
||||
uint32_t id = 0;
|
||||
};
|
||||
struct Receive {
|
||||
bool seen_packet = false;
|
||||
uint32_t last_cumulative_acked_tsn = 0;
|
||||
std::vector<OrderedStream> ordered_streams;
|
||||
std::vector<UnorderedStream> unordered_streams;
|
||||
};
|
||||
@ -42,7 +44,7 @@ struct DcSctpSocketHandoverState {
|
||||
enum class HandoverUnreadinessReason : uint32_t {
|
||||
kWrongConnectionState = 1,
|
||||
kSendQueueNotEmpty = 2,
|
||||
kDataTrackerNotIdle = 4,
|
||||
kPendingStreamResetRequest = 4,
|
||||
kDataTrackerTsnBlocksPending = 8,
|
||||
kReassemblyQueueNotEmpty = 16,
|
||||
kReassemblyQueueDeliveredTSNsGap = 32,
|
||||
@ -53,8 +55,7 @@ enum class HandoverUnreadinessReason : uint32_t {
|
||||
kRetransmissionQueueFastRecovery = 1024,
|
||||
kRetransmissionQueueNotEmpty = 2048,
|
||||
kPendingStreamReset = 4096,
|
||||
kPendingStreamResetRequest = 8192,
|
||||
kMax = kPendingStreamResetRequest,
|
||||
kMax = kPendingStreamReset,
|
||||
};
|
||||
|
||||
// Return value of `DcSctpSocketInterface::GetHandoverReadiness`. Set of
|
||||
|
||||
@ -17,6 +17,7 @@ rtc_library("data_tracker") {
|
||||
"../common:sequence_numbers",
|
||||
"../packet:chunk",
|
||||
"../packet:data",
|
||||
"../public:socket",
|
||||
"../timer",
|
||||
]
|
||||
sources = [
|
||||
|
||||
@ -356,4 +356,17 @@ absl::string_view DataTracker::ToString(AckState ack_state) {
|
||||
}
|
||||
}
|
||||
|
||||
HandoverReadinessStatus DataTracker::GetHandoverReadiness() const {
|
||||
HandoverReadinessStatus status;
|
||||
if (!additional_tsn_blocks_.empty()) {
|
||||
status.Add(HandoverUnreadinessReason::kDataTrackerTsnBlocksPending);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
void DataTracker::AddHandoverState(DcSctpSocketHandoverState& state) {
|
||||
state.rx.last_cumulative_acked_tsn = last_cumulative_acked_tsn().value();
|
||||
state.rx.seen_packet = seen_packet_;
|
||||
}
|
||||
|
||||
} // namespace dcsctp
|
||||
|
||||
@ -24,6 +24,7 @@
|
||||
#include "net/dcsctp/packet/chunk/data_common.h"
|
||||
#include "net/dcsctp/packet/chunk/sack_chunk.h"
|
||||
#include "net/dcsctp/packet/data.h"
|
||||
#include "net/dcsctp/public/dcsctp_handover_state.h"
|
||||
#include "net/dcsctp/timer/timer.h"
|
||||
|
||||
namespace dcsctp {
|
||||
@ -51,13 +52,17 @@ class DataTracker {
|
||||
// cumulative acked TSN.
|
||||
static constexpr uint32_t kMaxAcceptedOutstandingFragments = 100000;
|
||||
|
||||
explicit DataTracker(absl::string_view log_prefix,
|
||||
Timer* delayed_ack_timer,
|
||||
TSN peer_initial_tsn)
|
||||
DataTracker(absl::string_view log_prefix,
|
||||
Timer* delayed_ack_timer,
|
||||
TSN peer_initial_tsn,
|
||||
const DcSctpSocketHandoverState* handover_state = nullptr)
|
||||
: log_prefix_(std::string(log_prefix) + "dtrack: "),
|
||||
seen_packet_(handover_state != nullptr ? handover_state->rx.seen_packet
|
||||
: false),
|
||||
delayed_ack_timer_(*delayed_ack_timer),
|
||||
last_cumulative_acked_tsn_(
|
||||
tsn_unwrapper_.Unwrap(TSN(*peer_initial_tsn - 1))) {}
|
||||
last_cumulative_acked_tsn_(tsn_unwrapper_.Unwrap(
|
||||
handover_state ? TSN(handover_state->rx.last_cumulative_acked_tsn)
|
||||
: TSN(*peer_initial_tsn - 1))) {}
|
||||
|
||||
// Indicates if the provided TSN is valid. If this return false, the data
|
||||
// should be dropped and not added to any other buffers, which essentially
|
||||
@ -101,6 +106,10 @@ class DataTracker {
|
||||
|
||||
void HandleDelayedAckTimerExpiry();
|
||||
|
||||
HandoverReadinessStatus GetHandoverReadiness() const;
|
||||
|
||||
void AddHandoverState(DcSctpSocketHandoverState& state);
|
||||
|
||||
private:
|
||||
enum class AckState {
|
||||
// No need to send an ACK.
|
||||
@ -166,7 +175,7 @@ class DataTracker {
|
||||
|
||||
const std::string log_prefix_;
|
||||
// If a packet has ever been seen.
|
||||
bool seen_packet_ = false;
|
||||
bool seen_packet_;
|
||||
Timer& delayed_ack_timer_;
|
||||
AckState ack_state_ = AckState::kIdle;
|
||||
UnwrappedTSN::Unwrapper tsn_unwrapper_;
|
||||
|
||||
@ -40,23 +40,33 @@ class DataTrackerTest : public testing::Test {
|
||||
"test/delayed_ack",
|
||||
[]() { return absl::nullopt; },
|
||||
TimerOptions(DurationMs(0)))),
|
||||
buf_("log: ", timer_.get(), kInitialTSN) {}
|
||||
tracker_(
|
||||
std::make_unique<DataTracker>("log: ", timer_.get(), kInitialTSN)) {
|
||||
}
|
||||
|
||||
void Observer(std::initializer_list<uint32_t> tsns) {
|
||||
for (const uint32_t tsn : tsns) {
|
||||
buf_.Observe(TSN(tsn), AnyDataChunk::ImmediateAckFlag(false));
|
||||
tracker_->Observe(TSN(tsn), AnyDataChunk::ImmediateAckFlag(false));
|
||||
}
|
||||
}
|
||||
|
||||
void HandoverTracker() {
|
||||
EXPECT_TRUE(tracker_->GetHandoverReadiness().IsReady());
|
||||
DcSctpSocketHandoverState state;
|
||||
tracker_->AddHandoverState(state);
|
||||
tracker_ = std::make_unique<DataTracker>("log: ", timer_.get(), kInitialTSN,
|
||||
&state);
|
||||
}
|
||||
|
||||
TimeMs now_ = TimeMs(0);
|
||||
FakeTimeoutManager timeout_manager_;
|
||||
TimerManager timer_manager_;
|
||||
std::unique_ptr<Timer> timer_;
|
||||
DataTracker buf_;
|
||||
std::unique_ptr<DataTracker> tracker_;
|
||||
};
|
||||
|
||||
TEST_F(DataTrackerTest, Empty) {
|
||||
SackChunk sack = buf_.CreateSelectiveAck(kArwnd);
|
||||
SackChunk sack = tracker_->CreateSelectiveAck(kArwnd);
|
||||
EXPECT_EQ(sack.cumulative_tsn_ack(), TSN(10));
|
||||
EXPECT_THAT(sack.gap_ack_blocks(), IsEmpty());
|
||||
EXPECT_THAT(sack.duplicate_tsns(), IsEmpty());
|
||||
@ -64,7 +74,7 @@ TEST_F(DataTrackerTest, Empty) {
|
||||
|
||||
TEST_F(DataTrackerTest, ObserverSingleInOrderPacket) {
|
||||
Observer({11});
|
||||
SackChunk sack = buf_.CreateSelectiveAck(kArwnd);
|
||||
SackChunk sack = tracker_->CreateSelectiveAck(kArwnd);
|
||||
EXPECT_EQ(sack.cumulative_tsn_ack(), TSN(11));
|
||||
EXPECT_THAT(sack.gap_ack_blocks(), IsEmpty());
|
||||
EXPECT_THAT(sack.duplicate_tsns(), IsEmpty());
|
||||
@ -72,7 +82,7 @@ TEST_F(DataTrackerTest, ObserverSingleInOrderPacket) {
|
||||
|
||||
TEST_F(DataTrackerTest, ObserverManyInOrderMovesCumulativeTsnAck) {
|
||||
Observer({11, 12, 13});
|
||||
SackChunk sack = buf_.CreateSelectiveAck(kArwnd);
|
||||
SackChunk sack = tracker_->CreateSelectiveAck(kArwnd);
|
||||
EXPECT_EQ(sack.cumulative_tsn_ack(), TSN(13));
|
||||
EXPECT_THAT(sack.gap_ack_blocks(), IsEmpty());
|
||||
EXPECT_THAT(sack.duplicate_tsns(), IsEmpty());
|
||||
@ -80,7 +90,7 @@ TEST_F(DataTrackerTest, ObserverManyInOrderMovesCumulativeTsnAck) {
|
||||
|
||||
TEST_F(DataTrackerTest, ObserveOutOfOrderMovesCumulativeTsnAck) {
|
||||
Observer({12, 13, 14, 11});
|
||||
SackChunk sack = buf_.CreateSelectiveAck(kArwnd);
|
||||
SackChunk sack = tracker_->CreateSelectiveAck(kArwnd);
|
||||
EXPECT_EQ(sack.cumulative_tsn_ack(), TSN(14));
|
||||
EXPECT_THAT(sack.gap_ack_blocks(), IsEmpty());
|
||||
EXPECT_THAT(sack.duplicate_tsns(), IsEmpty());
|
||||
@ -88,7 +98,7 @@ TEST_F(DataTrackerTest, ObserveOutOfOrderMovesCumulativeTsnAck) {
|
||||
|
||||
TEST_F(DataTrackerTest, SingleGap) {
|
||||
Observer({12});
|
||||
SackChunk sack = buf_.CreateSelectiveAck(kArwnd);
|
||||
SackChunk sack = tracker_->CreateSelectiveAck(kArwnd);
|
||||
EXPECT_EQ(sack.cumulative_tsn_ack(), TSN(10));
|
||||
EXPECT_THAT(sack.gap_ack_blocks(), ElementsAre(SackChunk::GapAckBlock(2, 2)));
|
||||
EXPECT_THAT(sack.duplicate_tsns(), IsEmpty());
|
||||
@ -96,7 +106,7 @@ TEST_F(DataTrackerTest, SingleGap) {
|
||||
|
||||
TEST_F(DataTrackerTest, ExampleFromRFC4960Section334) {
|
||||
Observer({11, 12, 14, 15, 17});
|
||||
SackChunk sack = buf_.CreateSelectiveAck(kArwnd);
|
||||
SackChunk sack = tracker_->CreateSelectiveAck(kArwnd);
|
||||
EXPECT_EQ(sack.cumulative_tsn_ack(), TSN(12));
|
||||
EXPECT_THAT(sack.gap_ack_blocks(), ElementsAre(SackChunk::GapAckBlock(2, 3),
|
||||
SackChunk::GapAckBlock(5, 5)));
|
||||
@ -105,33 +115,33 @@ TEST_F(DataTrackerTest, ExampleFromRFC4960Section334) {
|
||||
|
||||
TEST_F(DataTrackerTest, AckAlreadyReceivedChunk) {
|
||||
Observer({11});
|
||||
SackChunk sack1 = buf_.CreateSelectiveAck(kArwnd);
|
||||
SackChunk sack1 = tracker_->CreateSelectiveAck(kArwnd);
|
||||
EXPECT_EQ(sack1.cumulative_tsn_ack(), TSN(11));
|
||||
EXPECT_THAT(sack1.gap_ack_blocks(), IsEmpty());
|
||||
|
||||
// Receive old chunk
|
||||
Observer({8});
|
||||
SackChunk sack2 = buf_.CreateSelectiveAck(kArwnd);
|
||||
SackChunk sack2 = tracker_->CreateSelectiveAck(kArwnd);
|
||||
EXPECT_EQ(sack2.cumulative_tsn_ack(), TSN(11));
|
||||
EXPECT_THAT(sack2.gap_ack_blocks(), IsEmpty());
|
||||
}
|
||||
|
||||
TEST_F(DataTrackerTest, DoubleSendRetransmittedChunk) {
|
||||
Observer({11, 13, 14, 15});
|
||||
SackChunk sack1 = buf_.CreateSelectiveAck(kArwnd);
|
||||
SackChunk sack1 = tracker_->CreateSelectiveAck(kArwnd);
|
||||
EXPECT_EQ(sack1.cumulative_tsn_ack(), TSN(11));
|
||||
EXPECT_THAT(sack1.gap_ack_blocks(),
|
||||
ElementsAre(SackChunk::GapAckBlock(2, 4)));
|
||||
|
||||
// Fill in the hole.
|
||||
Observer({12, 16, 17, 18});
|
||||
SackChunk sack2 = buf_.CreateSelectiveAck(kArwnd);
|
||||
SackChunk sack2 = tracker_->CreateSelectiveAck(kArwnd);
|
||||
EXPECT_EQ(sack2.cumulative_tsn_ack(), TSN(18));
|
||||
EXPECT_THAT(sack2.gap_ack_blocks(), IsEmpty());
|
||||
|
||||
// Receive chunk 12 again.
|
||||
Observer({12, 19, 20, 21});
|
||||
SackChunk sack3 = buf_.CreateSelectiveAck(kArwnd);
|
||||
SackChunk sack3 = tracker_->CreateSelectiveAck(kArwnd);
|
||||
EXPECT_EQ(sack3.cumulative_tsn_ack(), TSN(21));
|
||||
EXPECT_THAT(sack3.gap_ack_blocks(), IsEmpty());
|
||||
}
|
||||
@ -140,9 +150,9 @@ TEST_F(DataTrackerTest, ForwardTsnSimple) {
|
||||
// Messages (11, 12, 13), (14, 15) - first message expires.
|
||||
Observer({11, 12, 15});
|
||||
|
||||
buf_.HandleForwardTsn(TSN(13));
|
||||
tracker_->HandleForwardTsn(TSN(13));
|
||||
|
||||
SackChunk sack = buf_.CreateSelectiveAck(kArwnd);
|
||||
SackChunk sack = tracker_->CreateSelectiveAck(kArwnd);
|
||||
EXPECT_EQ(sack.cumulative_tsn_ack(), TSN(13));
|
||||
EXPECT_THAT(sack.gap_ack_blocks(), ElementsAre(SackChunk::GapAckBlock(2, 2)));
|
||||
}
|
||||
@ -151,21 +161,21 @@ TEST_F(DataTrackerTest, ForwardTsnSkipsFromGapBlock) {
|
||||
// Messages (11, 12, 13), (14, 15) - first message expires.
|
||||
Observer({11, 12, 14});
|
||||
|
||||
buf_.HandleForwardTsn(TSN(13));
|
||||
tracker_->HandleForwardTsn(TSN(13));
|
||||
|
||||
SackChunk sack = buf_.CreateSelectiveAck(kArwnd);
|
||||
SackChunk sack = tracker_->CreateSelectiveAck(kArwnd);
|
||||
EXPECT_EQ(sack.cumulative_tsn_ack(), TSN(14));
|
||||
EXPECT_THAT(sack.gap_ack_blocks(), IsEmpty());
|
||||
}
|
||||
|
||||
TEST_F(DataTrackerTest, ExampleFromRFC3758) {
|
||||
buf_.HandleForwardTsn(TSN(102));
|
||||
tracker_->HandleForwardTsn(TSN(102));
|
||||
|
||||
Observer({102, 104, 105, 107});
|
||||
|
||||
buf_.HandleForwardTsn(TSN(103));
|
||||
tracker_->HandleForwardTsn(TSN(103));
|
||||
|
||||
SackChunk sack = buf_.CreateSelectiveAck(kArwnd);
|
||||
SackChunk sack = tracker_->CreateSelectiveAck(kArwnd);
|
||||
EXPECT_EQ(sack.cumulative_tsn_ack(), TSN(105));
|
||||
EXPECT_THAT(sack.gap_ack_blocks(), ElementsAre(SackChunk::GapAckBlock(2, 2)));
|
||||
}
|
||||
@ -173,40 +183,40 @@ TEST_F(DataTrackerTest, ExampleFromRFC3758) {
|
||||
TEST_F(DataTrackerTest, EmptyAllAcks) {
|
||||
Observer({11, 13, 14, 15});
|
||||
|
||||
buf_.HandleForwardTsn(TSN(100));
|
||||
tracker_->HandleForwardTsn(TSN(100));
|
||||
|
||||
SackChunk sack = buf_.CreateSelectiveAck(kArwnd);
|
||||
SackChunk sack = tracker_->CreateSelectiveAck(kArwnd);
|
||||
EXPECT_EQ(sack.cumulative_tsn_ack(), TSN(100));
|
||||
EXPECT_THAT(sack.gap_ack_blocks(), IsEmpty());
|
||||
}
|
||||
|
||||
TEST_F(DataTrackerTest, SetsArwndCorrectly) {
|
||||
SackChunk sack1 = buf_.CreateSelectiveAck(/*a_rwnd=*/100);
|
||||
SackChunk sack1 = tracker_->CreateSelectiveAck(/*a_rwnd=*/100);
|
||||
EXPECT_EQ(sack1.a_rwnd(), 100u);
|
||||
|
||||
SackChunk sack2 = buf_.CreateSelectiveAck(/*a_rwnd=*/101);
|
||||
SackChunk sack2 = tracker_->CreateSelectiveAck(/*a_rwnd=*/101);
|
||||
EXPECT_EQ(sack2.a_rwnd(), 101u);
|
||||
}
|
||||
|
||||
TEST_F(DataTrackerTest, WillIncreaseCumAckTsn) {
|
||||
EXPECT_EQ(buf_.last_cumulative_acked_tsn(), TSN(10));
|
||||
EXPECT_FALSE(buf_.will_increase_cum_ack_tsn(TSN(10)));
|
||||
EXPECT_TRUE(buf_.will_increase_cum_ack_tsn(TSN(11)));
|
||||
EXPECT_FALSE(buf_.will_increase_cum_ack_tsn(TSN(12)));
|
||||
EXPECT_EQ(tracker_->last_cumulative_acked_tsn(), TSN(10));
|
||||
EXPECT_FALSE(tracker_->will_increase_cum_ack_tsn(TSN(10)));
|
||||
EXPECT_TRUE(tracker_->will_increase_cum_ack_tsn(TSN(11)));
|
||||
EXPECT_FALSE(tracker_->will_increase_cum_ack_tsn(TSN(12)));
|
||||
|
||||
Observer({11, 12, 13, 14, 15});
|
||||
EXPECT_EQ(buf_.last_cumulative_acked_tsn(), TSN(15));
|
||||
EXPECT_FALSE(buf_.will_increase_cum_ack_tsn(TSN(15)));
|
||||
EXPECT_TRUE(buf_.will_increase_cum_ack_tsn(TSN(16)));
|
||||
EXPECT_FALSE(buf_.will_increase_cum_ack_tsn(TSN(17)));
|
||||
EXPECT_EQ(tracker_->last_cumulative_acked_tsn(), TSN(15));
|
||||
EXPECT_FALSE(tracker_->will_increase_cum_ack_tsn(TSN(15)));
|
||||
EXPECT_TRUE(tracker_->will_increase_cum_ack_tsn(TSN(16)));
|
||||
EXPECT_FALSE(tracker_->will_increase_cum_ack_tsn(TSN(17)));
|
||||
}
|
||||
|
||||
TEST_F(DataTrackerTest, ForceShouldSendSackImmediately) {
|
||||
EXPECT_FALSE(buf_.ShouldSendAck());
|
||||
EXPECT_FALSE(tracker_->ShouldSendAck());
|
||||
|
||||
buf_.ForceImmediateSack();
|
||||
tracker_->ForceImmediateSack();
|
||||
|
||||
EXPECT_TRUE(buf_.ShouldSendAck());
|
||||
EXPECT_TRUE(tracker_->ShouldSendAck());
|
||||
}
|
||||
|
||||
TEST_F(DataTrackerTest, WillAcceptValidTSNs) {
|
||||
@ -215,7 +225,7 @@ TEST_F(DataTrackerTest, WillAcceptValidTSNs) {
|
||||
int limit = static_cast<int>(DataTracker::kMaxAcceptedOutstandingFragments);
|
||||
|
||||
for (int i = -limit; i <= limit; ++i) {
|
||||
EXPECT_TRUE(buf_.IsTSNValid(TSN(*last_tsn + i)));
|
||||
EXPECT_TRUE(tracker_->IsTSNValid(TSN(*last_tsn + i)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -224,15 +234,15 @@ TEST_F(DataTrackerTest, WillNotAcceptInvalidTSNs) {
|
||||
TSN last_tsn = TSN(*kInitialTSN - 1);
|
||||
|
||||
size_t limit = DataTracker::kMaxAcceptedOutstandingFragments;
|
||||
EXPECT_FALSE(buf_.IsTSNValid(TSN(*last_tsn + limit + 1)));
|
||||
EXPECT_FALSE(buf_.IsTSNValid(TSN(*last_tsn - (limit + 1))));
|
||||
EXPECT_FALSE(buf_.IsTSNValid(TSN(*last_tsn + 0x8000000)));
|
||||
EXPECT_FALSE(buf_.IsTSNValid(TSN(*last_tsn - 0x8000000)));
|
||||
EXPECT_FALSE(tracker_->IsTSNValid(TSN(*last_tsn + limit + 1)));
|
||||
EXPECT_FALSE(tracker_->IsTSNValid(TSN(*last_tsn - (limit + 1))));
|
||||
EXPECT_FALSE(tracker_->IsTSNValid(TSN(*last_tsn + 0x8000000)));
|
||||
EXPECT_FALSE(tracker_->IsTSNValid(TSN(*last_tsn - 0x8000000)));
|
||||
}
|
||||
|
||||
TEST_F(DataTrackerTest, ReportSingleDuplicateTsns) {
|
||||
Observer({11, 12, 11});
|
||||
SackChunk sack = buf_.CreateSelectiveAck(kArwnd);
|
||||
SackChunk sack = tracker_->CreateSelectiveAck(kArwnd);
|
||||
EXPECT_EQ(sack.cumulative_tsn_ack(), TSN(12));
|
||||
EXPECT_THAT(sack.gap_ack_blocks(), IsEmpty());
|
||||
EXPECT_THAT(sack.duplicate_tsns(), UnorderedElementsAre(TSN(11)));
|
||||
@ -240,7 +250,7 @@ TEST_F(DataTrackerTest, ReportSingleDuplicateTsns) {
|
||||
|
||||
TEST_F(DataTrackerTest, ReportMultipleDuplicateTsns) {
|
||||
Observer({11, 12, 13, 14, 12, 13, 12, 13, 15, 16});
|
||||
SackChunk sack = buf_.CreateSelectiveAck(kArwnd);
|
||||
SackChunk sack = tracker_->CreateSelectiveAck(kArwnd);
|
||||
EXPECT_EQ(sack.cumulative_tsn_ack(), TSN(16));
|
||||
EXPECT_THAT(sack.gap_ack_blocks(), IsEmpty());
|
||||
EXPECT_THAT(sack.duplicate_tsns(), UnorderedElementsAre(TSN(12), TSN(13)));
|
||||
@ -248,7 +258,7 @@ TEST_F(DataTrackerTest, ReportMultipleDuplicateTsns) {
|
||||
|
||||
TEST_F(DataTrackerTest, ReportDuplicateTsnsInGapAckBlocks) {
|
||||
Observer({11, /*12,*/ 13, 14, 13, 14, 15, 16});
|
||||
SackChunk sack = buf_.CreateSelectiveAck(kArwnd);
|
||||
SackChunk sack = tracker_->CreateSelectiveAck(kArwnd);
|
||||
EXPECT_EQ(sack.cumulative_tsn_ack(), TSN(11));
|
||||
EXPECT_THAT(sack.gap_ack_blocks(), ElementsAre(SackChunk::GapAckBlock(2, 5)));
|
||||
EXPECT_THAT(sack.duplicate_tsns(), UnorderedElementsAre(TSN(13), TSN(14)));
|
||||
@ -256,13 +266,13 @@ TEST_F(DataTrackerTest, ReportDuplicateTsnsInGapAckBlocks) {
|
||||
|
||||
TEST_F(DataTrackerTest, ClearsDuplicateTsnsAfterCreatingSack) {
|
||||
Observer({11, 12, 13, 14, 12, 13, 12, 13, 15, 16});
|
||||
SackChunk sack1 = buf_.CreateSelectiveAck(kArwnd);
|
||||
SackChunk sack1 = tracker_->CreateSelectiveAck(kArwnd);
|
||||
EXPECT_EQ(sack1.cumulative_tsn_ack(), TSN(16));
|
||||
EXPECT_THAT(sack1.gap_ack_blocks(), IsEmpty());
|
||||
EXPECT_THAT(sack1.duplicate_tsns(), UnorderedElementsAre(TSN(12), TSN(13)));
|
||||
|
||||
Observer({17});
|
||||
SackChunk sack2 = buf_.CreateSelectiveAck(kArwnd);
|
||||
SackChunk sack2 = tracker_->CreateSelectiveAck(kArwnd);
|
||||
EXPECT_EQ(sack2.cumulative_tsn_ack(), TSN(17));
|
||||
EXPECT_THAT(sack2.gap_ack_blocks(), IsEmpty());
|
||||
EXPECT_THAT(sack2.duplicate_tsns(), IsEmpty());
|
||||
@ -271,11 +281,11 @@ TEST_F(DataTrackerTest, ClearsDuplicateTsnsAfterCreatingSack) {
|
||||
TEST_F(DataTrackerTest, LimitsNumberOfDuplicatesReported) {
|
||||
for (size_t i = 0; i < DataTracker::kMaxDuplicateTsnReported + 10; ++i) {
|
||||
TSN tsn(11 + i);
|
||||
buf_.Observe(tsn, AnyDataChunk::ImmediateAckFlag(false));
|
||||
buf_.Observe(tsn, AnyDataChunk::ImmediateAckFlag(false));
|
||||
tracker_->Observe(tsn, AnyDataChunk::ImmediateAckFlag(false));
|
||||
tracker_->Observe(tsn, AnyDataChunk::ImmediateAckFlag(false));
|
||||
}
|
||||
|
||||
SackChunk sack = buf_.CreateSelectiveAck(kArwnd);
|
||||
SackChunk sack = tracker_->CreateSelectiveAck(kArwnd);
|
||||
EXPECT_THAT(sack.gap_ack_blocks(), IsEmpty());
|
||||
EXPECT_THAT(sack.duplicate_tsns(),
|
||||
SizeIs(DataTracker::kMaxDuplicateTsnReported));
|
||||
@ -284,10 +294,10 @@ TEST_F(DataTrackerTest, LimitsNumberOfDuplicatesReported) {
|
||||
TEST_F(DataTrackerTest, LimitsNumberOfGapAckBlocksReported) {
|
||||
for (size_t i = 0; i < DataTracker::kMaxGapAckBlocksReported + 10; ++i) {
|
||||
TSN tsn(11 + i * 2);
|
||||
buf_.Observe(tsn, AnyDataChunk::ImmediateAckFlag(false));
|
||||
tracker_->Observe(tsn, AnyDataChunk::ImmediateAckFlag(false));
|
||||
}
|
||||
|
||||
SackChunk sack = buf_.CreateSelectiveAck(kArwnd);
|
||||
SackChunk sack = tracker_->CreateSelectiveAck(kArwnd);
|
||||
EXPECT_EQ(sack.cumulative_tsn_ack(), TSN(11));
|
||||
EXPECT_THAT(sack.gap_ack_blocks(),
|
||||
SizeIs(DataTracker::kMaxGapAckBlocksReported));
|
||||
@ -295,99 +305,99 @@ TEST_F(DataTrackerTest, LimitsNumberOfGapAckBlocksReported) {
|
||||
|
||||
TEST_F(DataTrackerTest, SendsSackForFirstPacketObserved) {
|
||||
Observer({11});
|
||||
buf_.ObservePacketEnd();
|
||||
EXPECT_TRUE(buf_.ShouldSendAck());
|
||||
tracker_->ObservePacketEnd();
|
||||
EXPECT_TRUE(tracker_->ShouldSendAck());
|
||||
EXPECT_FALSE(timer_->is_running());
|
||||
}
|
||||
|
||||
TEST_F(DataTrackerTest, SendsSackEverySecondPacketWhenThereIsNoPacketLoss) {
|
||||
Observer({11});
|
||||
buf_.ObservePacketEnd();
|
||||
EXPECT_TRUE(buf_.ShouldSendAck());
|
||||
tracker_->ObservePacketEnd();
|
||||
EXPECT_TRUE(tracker_->ShouldSendAck());
|
||||
EXPECT_FALSE(timer_->is_running());
|
||||
Observer({12});
|
||||
buf_.ObservePacketEnd();
|
||||
EXPECT_FALSE(buf_.ShouldSendAck());
|
||||
tracker_->ObservePacketEnd();
|
||||
EXPECT_FALSE(tracker_->ShouldSendAck());
|
||||
EXPECT_TRUE(timer_->is_running());
|
||||
Observer({13});
|
||||
buf_.ObservePacketEnd();
|
||||
EXPECT_TRUE(buf_.ShouldSendAck());
|
||||
tracker_->ObservePacketEnd();
|
||||
EXPECT_TRUE(tracker_->ShouldSendAck());
|
||||
EXPECT_FALSE(timer_->is_running());
|
||||
Observer({14});
|
||||
buf_.ObservePacketEnd();
|
||||
EXPECT_FALSE(buf_.ShouldSendAck());
|
||||
tracker_->ObservePacketEnd();
|
||||
EXPECT_FALSE(tracker_->ShouldSendAck());
|
||||
EXPECT_TRUE(timer_->is_running());
|
||||
Observer({15});
|
||||
buf_.ObservePacketEnd();
|
||||
EXPECT_TRUE(buf_.ShouldSendAck());
|
||||
tracker_->ObservePacketEnd();
|
||||
EXPECT_TRUE(tracker_->ShouldSendAck());
|
||||
EXPECT_FALSE(timer_->is_running());
|
||||
}
|
||||
|
||||
TEST_F(DataTrackerTest, SendsSackEveryPacketOnPacketLoss) {
|
||||
Observer({11});
|
||||
buf_.ObservePacketEnd();
|
||||
EXPECT_TRUE(buf_.ShouldSendAck());
|
||||
tracker_->ObservePacketEnd();
|
||||
EXPECT_TRUE(tracker_->ShouldSendAck());
|
||||
EXPECT_FALSE(timer_->is_running());
|
||||
Observer({13});
|
||||
buf_.ObservePacketEnd();
|
||||
EXPECT_TRUE(buf_.ShouldSendAck());
|
||||
tracker_->ObservePacketEnd();
|
||||
EXPECT_TRUE(tracker_->ShouldSendAck());
|
||||
EXPECT_FALSE(timer_->is_running());
|
||||
Observer({14});
|
||||
buf_.ObservePacketEnd();
|
||||
EXPECT_TRUE(buf_.ShouldSendAck());
|
||||
tracker_->ObservePacketEnd();
|
||||
EXPECT_TRUE(tracker_->ShouldSendAck());
|
||||
EXPECT_FALSE(timer_->is_running());
|
||||
Observer({15});
|
||||
buf_.ObservePacketEnd();
|
||||
EXPECT_TRUE(buf_.ShouldSendAck());
|
||||
tracker_->ObservePacketEnd();
|
||||
EXPECT_TRUE(tracker_->ShouldSendAck());
|
||||
EXPECT_FALSE(timer_->is_running());
|
||||
Observer({16});
|
||||
buf_.ObservePacketEnd();
|
||||
EXPECT_TRUE(buf_.ShouldSendAck());
|
||||
tracker_->ObservePacketEnd();
|
||||
EXPECT_TRUE(tracker_->ShouldSendAck());
|
||||
EXPECT_FALSE(timer_->is_running());
|
||||
// Fill the hole.
|
||||
Observer({12});
|
||||
buf_.ObservePacketEnd();
|
||||
EXPECT_FALSE(buf_.ShouldSendAck());
|
||||
tracker_->ObservePacketEnd();
|
||||
EXPECT_FALSE(tracker_->ShouldSendAck());
|
||||
EXPECT_TRUE(timer_->is_running());
|
||||
// Goes back to every second packet
|
||||
Observer({17});
|
||||
buf_.ObservePacketEnd();
|
||||
EXPECT_TRUE(buf_.ShouldSendAck());
|
||||
tracker_->ObservePacketEnd();
|
||||
EXPECT_TRUE(tracker_->ShouldSendAck());
|
||||
EXPECT_FALSE(timer_->is_running());
|
||||
Observer({18});
|
||||
buf_.ObservePacketEnd();
|
||||
EXPECT_FALSE(buf_.ShouldSendAck());
|
||||
tracker_->ObservePacketEnd();
|
||||
EXPECT_FALSE(tracker_->ShouldSendAck());
|
||||
EXPECT_TRUE(timer_->is_running());
|
||||
}
|
||||
|
||||
TEST_F(DataTrackerTest, SendsSackOnDuplicateDataChunks) {
|
||||
Observer({11});
|
||||
buf_.ObservePacketEnd();
|
||||
EXPECT_TRUE(buf_.ShouldSendAck());
|
||||
tracker_->ObservePacketEnd();
|
||||
EXPECT_TRUE(tracker_->ShouldSendAck());
|
||||
EXPECT_FALSE(timer_->is_running());
|
||||
Observer({11});
|
||||
buf_.ObservePacketEnd();
|
||||
EXPECT_TRUE(buf_.ShouldSendAck());
|
||||
tracker_->ObservePacketEnd();
|
||||
EXPECT_TRUE(tracker_->ShouldSendAck());
|
||||
EXPECT_FALSE(timer_->is_running());
|
||||
Observer({12});
|
||||
buf_.ObservePacketEnd();
|
||||
EXPECT_FALSE(buf_.ShouldSendAck());
|
||||
tracker_->ObservePacketEnd();
|
||||
EXPECT_FALSE(tracker_->ShouldSendAck());
|
||||
EXPECT_TRUE(timer_->is_running());
|
||||
// Goes back to every second packet
|
||||
Observer({13});
|
||||
buf_.ObservePacketEnd();
|
||||
EXPECT_TRUE(buf_.ShouldSendAck());
|
||||
tracker_->ObservePacketEnd();
|
||||
EXPECT_TRUE(tracker_->ShouldSendAck());
|
||||
EXPECT_FALSE(timer_->is_running());
|
||||
// Duplicate again
|
||||
Observer({12});
|
||||
buf_.ObservePacketEnd();
|
||||
EXPECT_TRUE(buf_.ShouldSendAck());
|
||||
tracker_->ObservePacketEnd();
|
||||
EXPECT_TRUE(tracker_->ShouldSendAck());
|
||||
EXPECT_FALSE(timer_->is_running());
|
||||
}
|
||||
|
||||
TEST_F(DataTrackerTest, GapAckBlockAddSingleBlock) {
|
||||
Observer({12});
|
||||
SackChunk sack = buf_.CreateSelectiveAck(kArwnd);
|
||||
SackChunk sack = tracker_->CreateSelectiveAck(kArwnd);
|
||||
EXPECT_EQ(sack.cumulative_tsn_ack(), TSN(10));
|
||||
EXPECT_THAT(sack.gap_ack_blocks(), ElementsAre(SackChunk::GapAckBlock(2, 2)));
|
||||
}
|
||||
@ -395,7 +405,7 @@ TEST_F(DataTrackerTest, GapAckBlockAddSingleBlock) {
|
||||
TEST_F(DataTrackerTest, GapAckBlockAddsAnother) {
|
||||
Observer({12});
|
||||
Observer({14});
|
||||
SackChunk sack = buf_.CreateSelectiveAck(kArwnd);
|
||||
SackChunk sack = tracker_->CreateSelectiveAck(kArwnd);
|
||||
EXPECT_EQ(sack.cumulative_tsn_ack(), TSN(10));
|
||||
EXPECT_THAT(sack.gap_ack_blocks(), ElementsAre(SackChunk::GapAckBlock(2, 2),
|
||||
SackChunk::GapAckBlock(4, 4)));
|
||||
@ -404,7 +414,7 @@ TEST_F(DataTrackerTest, GapAckBlockAddsAnother) {
|
||||
TEST_F(DataTrackerTest, GapAckBlockAddsDuplicate) {
|
||||
Observer({12});
|
||||
Observer({12});
|
||||
SackChunk sack = buf_.CreateSelectiveAck(kArwnd);
|
||||
SackChunk sack = tracker_->CreateSelectiveAck(kArwnd);
|
||||
EXPECT_EQ(sack.cumulative_tsn_ack(), TSN(10));
|
||||
EXPECT_THAT(sack.gap_ack_blocks(), ElementsAre(SackChunk::GapAckBlock(2, 2)));
|
||||
EXPECT_THAT(sack.duplicate_tsns(), ElementsAre(TSN(12)));
|
||||
@ -413,7 +423,7 @@ TEST_F(DataTrackerTest, GapAckBlockAddsDuplicate) {
|
||||
TEST_F(DataTrackerTest, GapAckBlockExpandsToRight) {
|
||||
Observer({12});
|
||||
Observer({13});
|
||||
SackChunk sack = buf_.CreateSelectiveAck(kArwnd);
|
||||
SackChunk sack = tracker_->CreateSelectiveAck(kArwnd);
|
||||
EXPECT_EQ(sack.cumulative_tsn_ack(), TSN(10));
|
||||
EXPECT_THAT(sack.gap_ack_blocks(), ElementsAre(SackChunk::GapAckBlock(2, 3)));
|
||||
}
|
||||
@ -423,7 +433,7 @@ TEST_F(DataTrackerTest, GapAckBlockExpandsToRightWithOther) {
|
||||
Observer({20});
|
||||
Observer({30});
|
||||
Observer({21});
|
||||
SackChunk sack = buf_.CreateSelectiveAck(kArwnd);
|
||||
SackChunk sack = tracker_->CreateSelectiveAck(kArwnd);
|
||||
EXPECT_EQ(sack.cumulative_tsn_ack(), TSN(10));
|
||||
EXPECT_THAT(sack.gap_ack_blocks(),
|
||||
ElementsAre(SackChunk::GapAckBlock(2, 2), //
|
||||
@ -434,7 +444,7 @@ TEST_F(DataTrackerTest, GapAckBlockExpandsToRightWithOther) {
|
||||
TEST_F(DataTrackerTest, GapAckBlockExpandsToLeft) {
|
||||
Observer({13});
|
||||
Observer({12});
|
||||
SackChunk sack = buf_.CreateSelectiveAck(kArwnd);
|
||||
SackChunk sack = tracker_->CreateSelectiveAck(kArwnd);
|
||||
EXPECT_EQ(sack.cumulative_tsn_ack(), TSN(10));
|
||||
EXPECT_THAT(sack.gap_ack_blocks(), ElementsAre(SackChunk::GapAckBlock(2, 3)));
|
||||
}
|
||||
@ -444,7 +454,7 @@ TEST_F(DataTrackerTest, GapAckBlockExpandsToLeftWithOther) {
|
||||
Observer({21});
|
||||
Observer({30});
|
||||
Observer({20});
|
||||
SackChunk sack = buf_.CreateSelectiveAck(kArwnd);
|
||||
SackChunk sack = tracker_->CreateSelectiveAck(kArwnd);
|
||||
EXPECT_EQ(sack.cumulative_tsn_ack(), TSN(10));
|
||||
EXPECT_THAT(sack.gap_ack_blocks(),
|
||||
ElementsAre(SackChunk::GapAckBlock(2, 2), //
|
||||
@ -458,7 +468,7 @@ TEST_F(DataTrackerTest, GapAckBlockExpandsToLRightAndMerges) {
|
||||
Observer({22});
|
||||
Observer({30});
|
||||
Observer({21});
|
||||
SackChunk sack = buf_.CreateSelectiveAck(kArwnd);
|
||||
SackChunk sack = tracker_->CreateSelectiveAck(kArwnd);
|
||||
EXPECT_EQ(sack.cumulative_tsn_ack(), TSN(10));
|
||||
EXPECT_THAT(sack.gap_ack_blocks(),
|
||||
ElementsAre(SackChunk::GapAckBlock(2, 2), //
|
||||
@ -468,73 +478,73 @@ TEST_F(DataTrackerTest, GapAckBlockExpandsToLRightAndMerges) {
|
||||
|
||||
TEST_F(DataTrackerTest, GapAckBlockMergesManyBlocksIntoOne) {
|
||||
Observer({22});
|
||||
EXPECT_THAT(buf_.CreateSelectiveAck(kArwnd).gap_ack_blocks(),
|
||||
EXPECT_THAT(tracker_->CreateSelectiveAck(kArwnd).gap_ack_blocks(),
|
||||
ElementsAre(SackChunk::GapAckBlock(12, 12)));
|
||||
Observer({30});
|
||||
EXPECT_THAT(buf_.CreateSelectiveAck(kArwnd).gap_ack_blocks(),
|
||||
EXPECT_THAT(tracker_->CreateSelectiveAck(kArwnd).gap_ack_blocks(),
|
||||
ElementsAre(SackChunk::GapAckBlock(12, 12), //
|
||||
SackChunk::GapAckBlock(20, 20)));
|
||||
Observer({24});
|
||||
EXPECT_THAT(buf_.CreateSelectiveAck(kArwnd).gap_ack_blocks(),
|
||||
EXPECT_THAT(tracker_->CreateSelectiveAck(kArwnd).gap_ack_blocks(),
|
||||
ElementsAre(SackChunk::GapAckBlock(12, 12), //
|
||||
SackChunk::GapAckBlock(14, 14), //
|
||||
SackChunk::GapAckBlock(20, 20)));
|
||||
Observer({28});
|
||||
EXPECT_THAT(buf_.CreateSelectiveAck(kArwnd).gap_ack_blocks(),
|
||||
EXPECT_THAT(tracker_->CreateSelectiveAck(kArwnd).gap_ack_blocks(),
|
||||
ElementsAre(SackChunk::GapAckBlock(12, 12), //
|
||||
SackChunk::GapAckBlock(14, 14), //
|
||||
SackChunk::GapAckBlock(18, 18), //
|
||||
SackChunk::GapAckBlock(20, 20)));
|
||||
Observer({26});
|
||||
EXPECT_THAT(buf_.CreateSelectiveAck(kArwnd).gap_ack_blocks(),
|
||||
EXPECT_THAT(tracker_->CreateSelectiveAck(kArwnd).gap_ack_blocks(),
|
||||
ElementsAre(SackChunk::GapAckBlock(12, 12), //
|
||||
SackChunk::GapAckBlock(14, 14), //
|
||||
SackChunk::GapAckBlock(16, 16), //
|
||||
SackChunk::GapAckBlock(18, 18), //
|
||||
SackChunk::GapAckBlock(20, 20)));
|
||||
Observer({29});
|
||||
EXPECT_THAT(buf_.CreateSelectiveAck(kArwnd).gap_ack_blocks(),
|
||||
EXPECT_THAT(tracker_->CreateSelectiveAck(kArwnd).gap_ack_blocks(),
|
||||
ElementsAre(SackChunk::GapAckBlock(12, 12), //
|
||||
SackChunk::GapAckBlock(14, 14), //
|
||||
SackChunk::GapAckBlock(16, 16), //
|
||||
SackChunk::GapAckBlock(18, 20)));
|
||||
Observer({23});
|
||||
EXPECT_THAT(buf_.CreateSelectiveAck(kArwnd).gap_ack_blocks(),
|
||||
EXPECT_THAT(tracker_->CreateSelectiveAck(kArwnd).gap_ack_blocks(),
|
||||
ElementsAre(SackChunk::GapAckBlock(12, 14), //
|
||||
SackChunk::GapAckBlock(16, 16), //
|
||||
SackChunk::GapAckBlock(18, 20)));
|
||||
Observer({27});
|
||||
EXPECT_THAT(buf_.CreateSelectiveAck(kArwnd).gap_ack_blocks(),
|
||||
EXPECT_THAT(tracker_->CreateSelectiveAck(kArwnd).gap_ack_blocks(),
|
||||
ElementsAre(SackChunk::GapAckBlock(12, 14), //
|
||||
SackChunk::GapAckBlock(16, 20)));
|
||||
|
||||
Observer({25});
|
||||
EXPECT_THAT(buf_.CreateSelectiveAck(kArwnd).gap_ack_blocks(),
|
||||
EXPECT_THAT(tracker_->CreateSelectiveAck(kArwnd).gap_ack_blocks(),
|
||||
ElementsAre(SackChunk::GapAckBlock(12, 20)));
|
||||
Observer({20});
|
||||
EXPECT_THAT(buf_.CreateSelectiveAck(kArwnd).gap_ack_blocks(),
|
||||
EXPECT_THAT(tracker_->CreateSelectiveAck(kArwnd).gap_ack_blocks(),
|
||||
ElementsAre(SackChunk::GapAckBlock(10, 10), //
|
||||
SackChunk::GapAckBlock(12, 20)));
|
||||
Observer({32});
|
||||
EXPECT_THAT(buf_.CreateSelectiveAck(kArwnd).gap_ack_blocks(),
|
||||
EXPECT_THAT(tracker_->CreateSelectiveAck(kArwnd).gap_ack_blocks(),
|
||||
ElementsAre(SackChunk::GapAckBlock(10, 10), //
|
||||
SackChunk::GapAckBlock(12, 20), //
|
||||
SackChunk::GapAckBlock(22, 22)));
|
||||
Observer({21});
|
||||
EXPECT_THAT(buf_.CreateSelectiveAck(kArwnd).gap_ack_blocks(),
|
||||
EXPECT_THAT(tracker_->CreateSelectiveAck(kArwnd).gap_ack_blocks(),
|
||||
ElementsAre(SackChunk::GapAckBlock(10, 20), //
|
||||
SackChunk::GapAckBlock(22, 22)));
|
||||
Observer({31});
|
||||
EXPECT_THAT(buf_.CreateSelectiveAck(kArwnd).gap_ack_blocks(),
|
||||
EXPECT_THAT(tracker_->CreateSelectiveAck(kArwnd).gap_ack_blocks(),
|
||||
ElementsAre(SackChunk::GapAckBlock(10, 22)));
|
||||
}
|
||||
|
||||
TEST_F(DataTrackerTest, GapAckBlockRemoveBeforeCumAckTsn) {
|
||||
Observer({12, 13, 14, 20, 21, 22, 30, 31});
|
||||
|
||||
buf_.HandleForwardTsn(TSN(8));
|
||||
EXPECT_EQ(buf_.CreateSelectiveAck(kArwnd).cumulative_tsn_ack(), TSN(10));
|
||||
EXPECT_THAT(buf_.CreateSelectiveAck(kArwnd).gap_ack_blocks(),
|
||||
tracker_->HandleForwardTsn(TSN(8));
|
||||
EXPECT_EQ(tracker_->CreateSelectiveAck(kArwnd).cumulative_tsn_ack(), TSN(10));
|
||||
EXPECT_THAT(tracker_->CreateSelectiveAck(kArwnd).gap_ack_blocks(),
|
||||
ElementsAre(SackChunk::GapAckBlock(2, 4), //
|
||||
SackChunk::GapAckBlock(10, 12),
|
||||
SackChunk::GapAckBlock(20, 21)));
|
||||
@ -543,9 +553,9 @@ TEST_F(DataTrackerTest, GapAckBlockRemoveBeforeCumAckTsn) {
|
||||
TEST_F(DataTrackerTest, GapAckBlockRemoveBeforeFirstBlock) {
|
||||
Observer({12, 13, 14, 20, 21, 22, 30, 31});
|
||||
|
||||
buf_.HandleForwardTsn(TSN(11));
|
||||
EXPECT_EQ(buf_.CreateSelectiveAck(kArwnd).cumulative_tsn_ack(), TSN(14));
|
||||
EXPECT_THAT(buf_.CreateSelectiveAck(kArwnd).gap_ack_blocks(),
|
||||
tracker_->HandleForwardTsn(TSN(11));
|
||||
EXPECT_EQ(tracker_->CreateSelectiveAck(kArwnd).cumulative_tsn_ack(), TSN(14));
|
||||
EXPECT_THAT(tracker_->CreateSelectiveAck(kArwnd).gap_ack_blocks(),
|
||||
ElementsAre(SackChunk::GapAckBlock(6, 8), //
|
||||
SackChunk::GapAckBlock(16, 17)));
|
||||
}
|
||||
@ -553,27 +563,27 @@ TEST_F(DataTrackerTest, GapAckBlockRemoveBeforeFirstBlock) {
|
||||
TEST_F(DataTrackerTest, GapAckBlockRemoveAtBeginningOfFirstBlock) {
|
||||
Observer({12, 13, 14, 20, 21, 22, 30, 31});
|
||||
|
||||
buf_.HandleForwardTsn(TSN(12));
|
||||
EXPECT_EQ(buf_.CreateSelectiveAck(kArwnd).cumulative_tsn_ack(), TSN(14));
|
||||
EXPECT_THAT(buf_.CreateSelectiveAck(kArwnd).gap_ack_blocks(),
|
||||
tracker_->HandleForwardTsn(TSN(12));
|
||||
EXPECT_EQ(tracker_->CreateSelectiveAck(kArwnd).cumulative_tsn_ack(), TSN(14));
|
||||
EXPECT_THAT(tracker_->CreateSelectiveAck(kArwnd).gap_ack_blocks(),
|
||||
ElementsAre(SackChunk::GapAckBlock(6, 8), //
|
||||
SackChunk::GapAckBlock(16, 17)));
|
||||
}
|
||||
|
||||
TEST_F(DataTrackerTest, GapAckBlockRemoveAtMiddleOfFirstBlock) {
|
||||
Observer({12, 13, 14, 20, 21, 22, 30, 31});
|
||||
buf_.HandleForwardTsn(TSN(13));
|
||||
EXPECT_EQ(buf_.CreateSelectiveAck(kArwnd).cumulative_tsn_ack(), TSN(14));
|
||||
EXPECT_THAT(buf_.CreateSelectiveAck(kArwnd).gap_ack_blocks(),
|
||||
tracker_->HandleForwardTsn(TSN(13));
|
||||
EXPECT_EQ(tracker_->CreateSelectiveAck(kArwnd).cumulative_tsn_ack(), TSN(14));
|
||||
EXPECT_THAT(tracker_->CreateSelectiveAck(kArwnd).gap_ack_blocks(),
|
||||
ElementsAre(SackChunk::GapAckBlock(6, 8), //
|
||||
SackChunk::GapAckBlock(16, 17)));
|
||||
}
|
||||
|
||||
TEST_F(DataTrackerTest, GapAckBlockRemoveAtEndOfFirstBlock) {
|
||||
Observer({12, 13, 14, 20, 21, 22, 30, 31});
|
||||
buf_.HandleForwardTsn(TSN(14));
|
||||
EXPECT_EQ(buf_.CreateSelectiveAck(kArwnd).cumulative_tsn_ack(), TSN(14));
|
||||
EXPECT_THAT(buf_.CreateSelectiveAck(kArwnd).gap_ack_blocks(),
|
||||
tracker_->HandleForwardTsn(TSN(14));
|
||||
EXPECT_EQ(tracker_->CreateSelectiveAck(kArwnd).cumulative_tsn_ack(), TSN(14));
|
||||
EXPECT_THAT(tracker_->CreateSelectiveAck(kArwnd).gap_ack_blocks(),
|
||||
ElementsAre(SackChunk::GapAckBlock(6, 8), //
|
||||
SackChunk::GapAckBlock(16, 17)));
|
||||
}
|
||||
@ -581,9 +591,9 @@ TEST_F(DataTrackerTest, GapAckBlockRemoveAtEndOfFirstBlock) {
|
||||
TEST_F(DataTrackerTest, GapAckBlockRemoveRightAfterFirstBlock) {
|
||||
Observer({12, 13, 14, 20, 21, 22, 30, 31});
|
||||
|
||||
buf_.HandleForwardTsn(TSN(18));
|
||||
EXPECT_EQ(buf_.CreateSelectiveAck(kArwnd).cumulative_tsn_ack(), TSN(18));
|
||||
EXPECT_THAT(buf_.CreateSelectiveAck(kArwnd).gap_ack_blocks(),
|
||||
tracker_->HandleForwardTsn(TSN(18));
|
||||
EXPECT_EQ(tracker_->CreateSelectiveAck(kArwnd).cumulative_tsn_ack(), TSN(18));
|
||||
EXPECT_THAT(tracker_->CreateSelectiveAck(kArwnd).gap_ack_blocks(),
|
||||
ElementsAre(SackChunk::GapAckBlock(2, 4), //
|
||||
SackChunk::GapAckBlock(12, 13)));
|
||||
}
|
||||
@ -591,46 +601,117 @@ TEST_F(DataTrackerTest, GapAckBlockRemoveRightAfterFirstBlock) {
|
||||
TEST_F(DataTrackerTest, GapAckBlockRemoveRightBeforeSecondBlock) {
|
||||
Observer({12, 13, 14, 20, 21, 22, 30, 31});
|
||||
|
||||
buf_.HandleForwardTsn(TSN(19));
|
||||
EXPECT_EQ(buf_.CreateSelectiveAck(kArwnd).cumulative_tsn_ack(), TSN(22));
|
||||
EXPECT_THAT(buf_.CreateSelectiveAck(kArwnd).gap_ack_blocks(),
|
||||
tracker_->HandleForwardTsn(TSN(19));
|
||||
EXPECT_EQ(tracker_->CreateSelectiveAck(kArwnd).cumulative_tsn_ack(), TSN(22));
|
||||
EXPECT_THAT(tracker_->CreateSelectiveAck(kArwnd).gap_ack_blocks(),
|
||||
ElementsAre(SackChunk::GapAckBlock(8, 9)));
|
||||
}
|
||||
|
||||
TEST_F(DataTrackerTest, GapAckBlockRemoveRightAtStartOfSecondBlock) {
|
||||
Observer({12, 13, 14, 20, 21, 22, 30, 31});
|
||||
|
||||
buf_.HandleForwardTsn(TSN(20));
|
||||
EXPECT_EQ(buf_.CreateSelectiveAck(kArwnd).cumulative_tsn_ack(), TSN(22));
|
||||
EXPECT_THAT(buf_.CreateSelectiveAck(kArwnd).gap_ack_blocks(),
|
||||
tracker_->HandleForwardTsn(TSN(20));
|
||||
EXPECT_EQ(tracker_->CreateSelectiveAck(kArwnd).cumulative_tsn_ack(), TSN(22));
|
||||
EXPECT_THAT(tracker_->CreateSelectiveAck(kArwnd).gap_ack_blocks(),
|
||||
ElementsAre(SackChunk::GapAckBlock(8, 9)));
|
||||
}
|
||||
|
||||
TEST_F(DataTrackerTest, GapAckBlockRemoveRightAtMiddleOfSecondBlock) {
|
||||
Observer({12, 13, 14, 20, 21, 22, 30, 31});
|
||||
|
||||
buf_.HandleForwardTsn(TSN(21));
|
||||
EXPECT_EQ(buf_.CreateSelectiveAck(kArwnd).cumulative_tsn_ack(), TSN(22));
|
||||
EXPECT_THAT(buf_.CreateSelectiveAck(kArwnd).gap_ack_blocks(),
|
||||
tracker_->HandleForwardTsn(TSN(21));
|
||||
EXPECT_EQ(tracker_->CreateSelectiveAck(kArwnd).cumulative_tsn_ack(), TSN(22));
|
||||
EXPECT_THAT(tracker_->CreateSelectiveAck(kArwnd).gap_ack_blocks(),
|
||||
ElementsAre(SackChunk::GapAckBlock(8, 9)));
|
||||
}
|
||||
|
||||
TEST_F(DataTrackerTest, GapAckBlockRemoveRightAtEndOfSecondBlock) {
|
||||
Observer({12, 13, 14, 20, 21, 22, 30, 31});
|
||||
|
||||
buf_.HandleForwardTsn(TSN(22));
|
||||
EXPECT_EQ(buf_.CreateSelectiveAck(kArwnd).cumulative_tsn_ack(), TSN(22));
|
||||
EXPECT_THAT(buf_.CreateSelectiveAck(kArwnd).gap_ack_blocks(),
|
||||
tracker_->HandleForwardTsn(TSN(22));
|
||||
EXPECT_EQ(tracker_->CreateSelectiveAck(kArwnd).cumulative_tsn_ack(), TSN(22));
|
||||
EXPECT_THAT(tracker_->CreateSelectiveAck(kArwnd).gap_ack_blocks(),
|
||||
ElementsAre(SackChunk::GapAckBlock(8, 9)));
|
||||
}
|
||||
|
||||
TEST_F(DataTrackerTest, GapAckBlockRemoveeFarAfterAllBlocks) {
|
||||
Observer({12, 13, 14, 20, 21, 22, 30, 31});
|
||||
|
||||
buf_.HandleForwardTsn(TSN(40));
|
||||
EXPECT_EQ(buf_.CreateSelectiveAck(kArwnd).cumulative_tsn_ack(), TSN(40));
|
||||
EXPECT_THAT(buf_.CreateSelectiveAck(kArwnd).gap_ack_blocks(), IsEmpty());
|
||||
tracker_->HandleForwardTsn(TSN(40));
|
||||
EXPECT_EQ(tracker_->CreateSelectiveAck(kArwnd).cumulative_tsn_ack(), TSN(40));
|
||||
EXPECT_THAT(tracker_->CreateSelectiveAck(kArwnd).gap_ack_blocks(), IsEmpty());
|
||||
}
|
||||
|
||||
TEST_F(DataTrackerTest, HandoverEmpty) {
|
||||
HandoverTracker();
|
||||
Observer({11});
|
||||
SackChunk sack = tracker_->CreateSelectiveAck(kArwnd);
|
||||
EXPECT_EQ(sack.cumulative_tsn_ack(), TSN(11));
|
||||
EXPECT_THAT(sack.gap_ack_blocks(), IsEmpty());
|
||||
}
|
||||
|
||||
TEST_F(DataTrackerTest,
|
||||
HandoverWhileSendingSackEverySecondPacketWhenThereIsNoPacketLoss) {
|
||||
Observer({11});
|
||||
tracker_->ObservePacketEnd();
|
||||
EXPECT_TRUE(tracker_->ShouldSendAck());
|
||||
|
||||
HandoverTracker();
|
||||
|
||||
Observer({12});
|
||||
tracker_->ObservePacketEnd();
|
||||
EXPECT_FALSE(tracker_->ShouldSendAck());
|
||||
Observer({13});
|
||||
tracker_->ObservePacketEnd();
|
||||
EXPECT_TRUE(tracker_->ShouldSendAck());
|
||||
EXPECT_FALSE(timer_->is_running());
|
||||
Observer({14});
|
||||
tracker_->ObservePacketEnd();
|
||||
EXPECT_FALSE(tracker_->ShouldSendAck());
|
||||
EXPECT_TRUE(timer_->is_running());
|
||||
Observer({15});
|
||||
tracker_->ObservePacketEnd();
|
||||
EXPECT_TRUE(tracker_->ShouldSendAck());
|
||||
EXPECT_FALSE(timer_->is_running());
|
||||
}
|
||||
|
||||
TEST_F(DataTrackerTest, HandoverWhileSendingSackEveryPacketOnPacketLoss) {
|
||||
Observer({11});
|
||||
tracker_->ObservePacketEnd();
|
||||
EXPECT_TRUE(tracker_->ShouldSendAck());
|
||||
Observer({13});
|
||||
EXPECT_EQ(tracker_->GetHandoverReadiness(),
|
||||
HandoverReadinessStatus().Add(
|
||||
HandoverUnreadinessReason::kDataTrackerTsnBlocksPending));
|
||||
tracker_->ObservePacketEnd();
|
||||
EXPECT_TRUE(tracker_->ShouldSendAck());
|
||||
Observer({14});
|
||||
tracker_->ObservePacketEnd();
|
||||
EXPECT_TRUE(tracker_->ShouldSendAck());
|
||||
EXPECT_EQ(tracker_->GetHandoverReadiness(),
|
||||
HandoverReadinessStatus(
|
||||
HandoverUnreadinessReason::kDataTrackerTsnBlocksPending));
|
||||
Observer({15});
|
||||
tracker_->ObservePacketEnd();
|
||||
EXPECT_TRUE(tracker_->ShouldSendAck());
|
||||
Observer({16});
|
||||
tracker_->ObservePacketEnd();
|
||||
EXPECT_TRUE(tracker_->ShouldSendAck());
|
||||
// Fill the hole.
|
||||
Observer({12});
|
||||
tracker_->ObservePacketEnd();
|
||||
EXPECT_FALSE(tracker_->ShouldSendAck());
|
||||
// Goes back to every second packet
|
||||
Observer({17});
|
||||
tracker_->ObservePacketEnd();
|
||||
EXPECT_TRUE(tracker_->ShouldSendAck());
|
||||
|
||||
HandoverTracker();
|
||||
|
||||
Observer({18});
|
||||
tracker_->ObservePacketEnd();
|
||||
EXPECT_FALSE(tracker_->ShouldSendAck());
|
||||
EXPECT_TRUE(timer_->is_running());
|
||||
}
|
||||
} // namespace
|
||||
} // namespace dcsctp
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user