1 /*
2 * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10 #include "net/dcsctp/tx/outstanding_data.h"
11
12 #include <vector>
13
14 #include "absl/types/optional.h"
15 #include "net/dcsctp/common/math.h"
16 #include "net/dcsctp/common/sequence_numbers.h"
17 #include "net/dcsctp/packet/chunk/data_chunk.h"
18 #include "net/dcsctp/packet/chunk/forward_tsn_chunk.h"
19 #include "net/dcsctp/public/types.h"
20 #include "net/dcsctp/testing/data_generator.h"
21 #include "net/dcsctp/testing/testing_macros.h"
22 #include "rtc_base/gunit.h"
23 #include "test/gmock.h"
24
25 namespace dcsctp {
26 namespace {
27 using ::testing::MockFunction;
28 using State = ::dcsctp::OutstandingData::State;
29 using ::testing::_;
30 using ::testing::ElementsAre;
31 using ::testing::IsEmpty;
32 using ::testing::Pair;
33 using ::testing::Return;
34 using ::testing::StrictMock;
35
36 constexpr TimeMs kNow(42);
37
38 class OutstandingDataTest : public testing::Test {
39 protected:
OutstandingDataTest()40 OutstandingDataTest()
41 : gen_(MID(42)),
42 buf_(DataChunk::kHeaderSize,
43 unwrapper_.Unwrap(TSN(10)),
44 unwrapper_.Unwrap(TSN(9)),
45 on_discard_.AsStdFunction()) {}
46
47 UnwrappedTSN::Unwrapper unwrapper_;
48 DataGenerator gen_;
49 StrictMock<MockFunction<bool(IsUnordered, StreamID, MID)>> on_discard_;
50 OutstandingData buf_;
51 };
52
TEST_F(OutstandingDataTest,HasInitialState)53 TEST_F(OutstandingDataTest, HasInitialState) {
54 EXPECT_TRUE(buf_.empty());
55 EXPECT_EQ(buf_.outstanding_bytes(), 0u);
56 EXPECT_EQ(buf_.outstanding_items(), 0u);
57 EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
58 EXPECT_EQ(buf_.last_cumulative_tsn_ack().Wrap(), TSN(9));
59 EXPECT_EQ(buf_.next_tsn().Wrap(), TSN(10));
60 EXPECT_EQ(buf_.highest_outstanding_tsn().Wrap(), TSN(9));
61 EXPECT_THAT(buf_.GetChunkStatesForTesting(),
62 ElementsAre(Pair(TSN(9), State::kAcked)));
63 EXPECT_FALSE(buf_.ShouldSendForwardTsn());
64 }
65
TEST_F(OutstandingDataTest,InsertChunk)66 TEST_F(OutstandingDataTest, InsertChunk) {
67 ASSERT_HAS_VALUE_AND_ASSIGN(UnwrappedTSN tsn,
68 buf_.Insert(gen_.Ordered({1}, "BE"), kNow));
69
70 EXPECT_EQ(tsn.Wrap(), TSN(10));
71
72 EXPECT_EQ(buf_.outstanding_bytes(), DataChunk::kHeaderSize + RoundUpTo4(1));
73 EXPECT_EQ(buf_.outstanding_items(), 1u);
74 EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
75 EXPECT_EQ(buf_.last_cumulative_tsn_ack().Wrap(), TSN(9));
76 EXPECT_EQ(buf_.next_tsn().Wrap(), TSN(11));
77 EXPECT_EQ(buf_.highest_outstanding_tsn().Wrap(), TSN(10));
78 EXPECT_THAT(buf_.GetChunkStatesForTesting(),
79 ElementsAre(Pair(TSN(9), State::kAcked),
80 Pair(TSN(10), State::kInFlight)));
81 }
82
TEST_F(OutstandingDataTest,AcksSingleChunk)83 TEST_F(OutstandingDataTest, AcksSingleChunk) {
84 buf_.Insert(gen_.Ordered({1}, "BE"), kNow);
85 OutstandingData::AckInfo ack =
86 buf_.HandleSack(unwrapper_.Unwrap(TSN(10)), {}, false);
87
88 EXPECT_EQ(ack.bytes_acked, DataChunk::kHeaderSize + RoundUpTo4(1));
89 EXPECT_EQ(ack.highest_tsn_acked.Wrap(), TSN(10));
90 EXPECT_FALSE(ack.has_packet_loss);
91
92 EXPECT_EQ(buf_.outstanding_bytes(), 0u);
93 EXPECT_EQ(buf_.outstanding_items(), 0u);
94 EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
95 EXPECT_EQ(buf_.last_cumulative_tsn_ack().Wrap(), TSN(10));
96 EXPECT_EQ(buf_.next_tsn().Wrap(), TSN(11));
97 EXPECT_EQ(buf_.highest_outstanding_tsn().Wrap(), TSN(10));
98 EXPECT_THAT(buf_.GetChunkStatesForTesting(),
99 ElementsAre(Pair(TSN(10), State::kAcked)));
100 }
101
TEST_F(OutstandingDataTest,AcksPreviousChunkDoesntUpdate)102 TEST_F(OutstandingDataTest, AcksPreviousChunkDoesntUpdate) {
103 buf_.Insert(gen_.Ordered({1}, "BE"), kNow);
104 buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), {}, false);
105
106 EXPECT_EQ(buf_.outstanding_bytes(), DataChunk::kHeaderSize + RoundUpTo4(1));
107 EXPECT_EQ(buf_.outstanding_items(), 1u);
108 EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
109 EXPECT_EQ(buf_.last_cumulative_tsn_ack().Wrap(), TSN(9));
110 EXPECT_EQ(buf_.next_tsn().Wrap(), TSN(11));
111 EXPECT_EQ(buf_.highest_outstanding_tsn().Wrap(), TSN(10));
112 EXPECT_THAT(buf_.GetChunkStatesForTesting(),
113 ElementsAre(Pair(TSN(9), State::kAcked),
114 Pair(TSN(10), State::kInFlight)));
115 }
116
TEST_F(OutstandingDataTest,AcksAndNacksWithGapAckBlocks)117 TEST_F(OutstandingDataTest, AcksAndNacksWithGapAckBlocks) {
118 buf_.Insert(gen_.Ordered({1}, "B"), kNow);
119 buf_.Insert(gen_.Ordered({1}, "E"), kNow);
120
121 std::vector<SackChunk::GapAckBlock> gab = {SackChunk::GapAckBlock(2, 2)};
122 OutstandingData::AckInfo ack =
123 buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab, false);
124 EXPECT_EQ(ack.bytes_acked, DataChunk::kHeaderSize + RoundUpTo4(1));
125 EXPECT_EQ(ack.highest_tsn_acked.Wrap(), TSN(11));
126 EXPECT_FALSE(ack.has_packet_loss);
127
128 EXPECT_EQ(buf_.outstanding_bytes(), 0u);
129 EXPECT_EQ(buf_.outstanding_items(), 0u);
130 EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
131 EXPECT_EQ(buf_.last_cumulative_tsn_ack().Wrap(), TSN(9));
132 EXPECT_EQ(buf_.next_tsn().Wrap(), TSN(12));
133 EXPECT_EQ(buf_.highest_outstanding_tsn().Wrap(), TSN(11));
134 EXPECT_THAT(buf_.GetChunkStatesForTesting(),
135 ElementsAre(Pair(TSN(9), State::kAcked), //
136 Pair(TSN(10), State::kNacked), //
137 Pair(TSN(11), State::kAcked)));
138 }
139
TEST_F(OutstandingDataTest,NacksThreeTimesWithSameTsnDoesntRetransmit)140 TEST_F(OutstandingDataTest, NacksThreeTimesWithSameTsnDoesntRetransmit) {
141 buf_.Insert(gen_.Ordered({1}, "B"), kNow);
142 buf_.Insert(gen_.Ordered({1}, "E"), kNow);
143
144 std::vector<SackChunk::GapAckBlock> gab1 = {SackChunk::GapAckBlock(2, 2)};
145 EXPECT_FALSE(
146 buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab1, false).has_packet_loss);
147 EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
148
149 EXPECT_FALSE(
150 buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab1, false).has_packet_loss);
151 EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
152
153 EXPECT_FALSE(
154 buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab1, false).has_packet_loss);
155 EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
156
157 EXPECT_THAT(buf_.GetChunkStatesForTesting(),
158 ElementsAre(Pair(TSN(9), State::kAcked), //
159 Pair(TSN(10), State::kNacked), //
160 Pair(TSN(11), State::kAcked)));
161 }
162
TEST_F(OutstandingDataTest,NacksThreeTimesResultsInRetransmission)163 TEST_F(OutstandingDataTest, NacksThreeTimesResultsInRetransmission) {
164 buf_.Insert(gen_.Ordered({1}, "B"), kNow);
165 buf_.Insert(gen_.Ordered({1}, ""), kNow);
166 buf_.Insert(gen_.Ordered({1}, ""), kNow);
167 buf_.Insert(gen_.Ordered({1}, "E"), kNow);
168
169 std::vector<SackChunk::GapAckBlock> gab1 = {SackChunk::GapAckBlock(2, 2)};
170 EXPECT_FALSE(
171 buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab1, false).has_packet_loss);
172 EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
173
174 std::vector<SackChunk::GapAckBlock> gab2 = {SackChunk::GapAckBlock(2, 3)};
175 EXPECT_FALSE(
176 buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab2, false).has_packet_loss);
177 EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
178
179 std::vector<SackChunk::GapAckBlock> gab3 = {SackChunk::GapAckBlock(2, 4)};
180 OutstandingData::AckInfo ack =
181 buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab3, false);
182 EXPECT_EQ(ack.bytes_acked, DataChunk::kHeaderSize + RoundUpTo4(1));
183 EXPECT_EQ(ack.highest_tsn_acked.Wrap(), TSN(13));
184 EXPECT_TRUE(ack.has_packet_loss);
185
186 EXPECT_TRUE(buf_.has_data_to_be_retransmitted());
187
188 EXPECT_THAT(buf_.GetChunkStatesForTesting(),
189 ElementsAre(Pair(TSN(9), State::kAcked), //
190 Pair(TSN(10), State::kToBeRetransmitted), //
191 Pair(TSN(11), State::kAcked), //
192 Pair(TSN(12), State::kAcked), //
193 Pair(TSN(13), State::kAcked)));
194
195 EXPECT_THAT(buf_.GetChunksToBeFastRetransmitted(1000),
196 ElementsAre(Pair(TSN(10), _)));
197 EXPECT_THAT(buf_.GetChunksToBeRetransmitted(1000), IsEmpty());
198 }
199
TEST_F(OutstandingDataTest,NacksThreeTimesResultsInAbandoning)200 TEST_F(OutstandingDataTest, NacksThreeTimesResultsInAbandoning) {
201 static constexpr MaxRetransmits kMaxRetransmissions(0);
202 buf_.Insert(gen_.Ordered({1}, "B"), kNow, kMaxRetransmissions);
203 buf_.Insert(gen_.Ordered({1}, ""), kNow, kMaxRetransmissions);
204 buf_.Insert(gen_.Ordered({1}, ""), kNow, kMaxRetransmissions);
205 buf_.Insert(gen_.Ordered({1}, "E"), kNow, kMaxRetransmissions);
206
207 std::vector<SackChunk::GapAckBlock> gab1 = {SackChunk::GapAckBlock(2, 2)};
208 EXPECT_FALSE(
209 buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab1, false).has_packet_loss);
210 EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
211
212 std::vector<SackChunk::GapAckBlock> gab2 = {SackChunk::GapAckBlock(2, 3)};
213 EXPECT_FALSE(
214 buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab2, false).has_packet_loss);
215 EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
216
217 EXPECT_CALL(on_discard_, Call(IsUnordered(false), StreamID(1), MID(42)))
218 .WillOnce(Return(false));
219 std::vector<SackChunk::GapAckBlock> gab3 = {SackChunk::GapAckBlock(2, 4)};
220 OutstandingData::AckInfo ack =
221 buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab3, false);
222 EXPECT_EQ(ack.bytes_acked, DataChunk::kHeaderSize + RoundUpTo4(1));
223 EXPECT_EQ(ack.highest_tsn_acked.Wrap(), TSN(13));
224 EXPECT_TRUE(ack.has_packet_loss);
225
226 EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
227 EXPECT_EQ(buf_.next_tsn().Wrap(), TSN(14));
228 EXPECT_THAT(buf_.GetChunkStatesForTesting(),
229 ElementsAre(Pair(TSN(9), State::kAcked), //
230 Pair(TSN(10), State::kAbandoned), //
231 Pair(TSN(11), State::kAbandoned), //
232 Pair(TSN(12), State::kAbandoned), //
233 Pair(TSN(13), State::kAbandoned)));
234 }
235
TEST_F(OutstandingDataTest,NacksThreeTimesResultsInAbandoningWithPlaceholder)236 TEST_F(OutstandingDataTest, NacksThreeTimesResultsInAbandoningWithPlaceholder) {
237 static constexpr MaxRetransmits kMaxRetransmissions(0);
238 buf_.Insert(gen_.Ordered({1}, "B"), kNow, kMaxRetransmissions);
239 buf_.Insert(gen_.Ordered({1}, ""), kNow, kMaxRetransmissions);
240 buf_.Insert(gen_.Ordered({1}, ""), kNow, kMaxRetransmissions);
241 buf_.Insert(gen_.Ordered({1}, ""), kNow, kMaxRetransmissions);
242
243 std::vector<SackChunk::GapAckBlock> gab1 = {SackChunk::GapAckBlock(2, 2)};
244 EXPECT_FALSE(
245 buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab1, false).has_packet_loss);
246 EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
247
248 std::vector<SackChunk::GapAckBlock> gab2 = {SackChunk::GapAckBlock(2, 3)};
249 EXPECT_FALSE(
250 buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab2, false).has_packet_loss);
251 EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
252
253 EXPECT_CALL(on_discard_, Call(IsUnordered(false), StreamID(1), MID(42)))
254 .WillOnce(Return(true));
255 std::vector<SackChunk::GapAckBlock> gab3 = {SackChunk::GapAckBlock(2, 4)};
256 OutstandingData::AckInfo ack =
257 buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab3, false);
258 EXPECT_EQ(ack.bytes_acked, DataChunk::kHeaderSize + RoundUpTo4(1));
259 EXPECT_EQ(ack.highest_tsn_acked.Wrap(), TSN(13));
260 EXPECT_TRUE(ack.has_packet_loss);
261
262 EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
263 EXPECT_EQ(buf_.next_tsn().Wrap(), TSN(15));
264 EXPECT_THAT(buf_.GetChunkStatesForTesting(),
265 ElementsAre(Pair(TSN(9), State::kAcked), //
266 Pair(TSN(10), State::kAbandoned), //
267 Pair(TSN(11), State::kAbandoned), //
268 Pair(TSN(12), State::kAbandoned), //
269 Pair(TSN(13), State::kAbandoned), //
270 Pair(TSN(14), State::kAbandoned)));
271 }
272
TEST_F(OutstandingDataTest,ExpiresChunkBeforeItIsInserted)273 TEST_F(OutstandingDataTest, ExpiresChunkBeforeItIsInserted) {
274 static constexpr TimeMs kExpiresAt = kNow + DurationMs(1);
275 EXPECT_TRUE(buf_.Insert(gen_.Ordered({1}, "B"), kNow,
276 MaxRetransmits::NoLimit(), kExpiresAt)
277 .has_value());
278 EXPECT_TRUE(buf_.Insert(gen_.Ordered({1}, ""), kNow + DurationMs(0),
279 MaxRetransmits::NoLimit(), kExpiresAt)
280 .has_value());
281
282 EXPECT_CALL(on_discard_, Call(IsUnordered(false), StreamID(1), MID(42)))
283 .WillOnce(Return(false));
284 EXPECT_FALSE(buf_.Insert(gen_.Ordered({1}, "E"), kNow + DurationMs(1),
285 MaxRetransmits::NoLimit(), kExpiresAt)
286 .has_value());
287
288 EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
289 EXPECT_EQ(buf_.last_cumulative_tsn_ack().Wrap(), TSN(9));
290 EXPECT_EQ(buf_.next_tsn().Wrap(), TSN(13));
291 EXPECT_EQ(buf_.highest_outstanding_tsn().Wrap(), TSN(12));
292 EXPECT_THAT(buf_.GetChunkStatesForTesting(),
293 ElementsAre(Pair(TSN(9), State::kAcked), //
294 Pair(TSN(10), State::kAbandoned), //
295 Pair(TSN(11), State::kAbandoned),
296 Pair(TSN(12), State::kAbandoned)));
297 }
298
TEST_F(OutstandingDataTest,CanGenerateForwardTsn)299 TEST_F(OutstandingDataTest, CanGenerateForwardTsn) {
300 static constexpr MaxRetransmits kMaxRetransmissions(0);
301 buf_.Insert(gen_.Ordered({1}, "B"), kNow, kMaxRetransmissions);
302 buf_.Insert(gen_.Ordered({1}, ""), kNow, kMaxRetransmissions);
303 buf_.Insert(gen_.Ordered({1}, "E"), kNow, kMaxRetransmissions);
304
305 EXPECT_CALL(on_discard_, Call(IsUnordered(false), StreamID(1), MID(42)))
306 .WillOnce(Return(false));
307 buf_.NackAll();
308
309 EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
310 EXPECT_THAT(buf_.GetChunkStatesForTesting(),
311 ElementsAre(Pair(TSN(9), State::kAcked), //
312 Pair(TSN(10), State::kAbandoned), //
313 Pair(TSN(11), State::kAbandoned),
314 Pair(TSN(12), State::kAbandoned)));
315
316 EXPECT_TRUE(buf_.ShouldSendForwardTsn());
317 ForwardTsnChunk chunk = buf_.CreateForwardTsn();
318 EXPECT_EQ(chunk.new_cumulative_tsn(), TSN(12));
319 }
320
TEST_F(OutstandingDataTest,AckWithGapBlocksFromRFC4960Section334)321 TEST_F(OutstandingDataTest, AckWithGapBlocksFromRFC4960Section334) {
322 buf_.Insert(gen_.Ordered({1}, "B"), kNow);
323 buf_.Insert(gen_.Ordered({1}, ""), kNow);
324 buf_.Insert(gen_.Ordered({1}, ""), kNow);
325 buf_.Insert(gen_.Ordered({1}, ""), kNow);
326 buf_.Insert(gen_.Ordered({1}, ""), kNow);
327 buf_.Insert(gen_.Ordered({1}, ""), kNow);
328 buf_.Insert(gen_.Ordered({1}, ""), kNow);
329 buf_.Insert(gen_.Ordered({1}, "E"), kNow);
330
331 EXPECT_THAT(buf_.GetChunkStatesForTesting(),
332 testing::ElementsAre(Pair(TSN(9), State::kAcked), //
333 Pair(TSN(10), State::kInFlight), //
334 Pair(TSN(11), State::kInFlight), //
335 Pair(TSN(12), State::kInFlight), //
336 Pair(TSN(13), State::kInFlight), //
337 Pair(TSN(14), State::kInFlight), //
338 Pair(TSN(15), State::kInFlight), //
339 Pair(TSN(16), State::kInFlight), //
340 Pair(TSN(17), State::kInFlight)));
341
342 std::vector<SackChunk::GapAckBlock> gab = {SackChunk::GapAckBlock(2, 3),
343 SackChunk::GapAckBlock(5, 5)};
344 buf_.HandleSack(unwrapper_.Unwrap(TSN(12)), gab, false);
345
346 EXPECT_THAT(buf_.GetChunkStatesForTesting(),
347 ElementsAre(Pair(TSN(12), State::kAcked), //
348 Pair(TSN(13), State::kNacked), //
349 Pair(TSN(14), State::kAcked), //
350 Pair(TSN(15), State::kAcked), //
351 Pair(TSN(16), State::kNacked), //
352 Pair(TSN(17), State::kAcked)));
353 }
354
TEST_F(OutstandingDataTest,MeasureRTT)355 TEST_F(OutstandingDataTest, MeasureRTT) {
356 buf_.Insert(gen_.Ordered({1}, "BE"), kNow);
357 buf_.Insert(gen_.Ordered({1}, "BE"), kNow + DurationMs(1));
358 buf_.Insert(gen_.Ordered({1}, "BE"), kNow + DurationMs(2));
359
360 static constexpr DurationMs kDuration(123);
361 ASSERT_HAS_VALUE_AND_ASSIGN(
362 DurationMs duration,
363 buf_.MeasureRTT(kNow + kDuration, unwrapper_.Unwrap(TSN(11))));
364
365 EXPECT_EQ(duration, kDuration - DurationMs(1));
366 }
367
TEST_F(OutstandingDataTest,MustRetransmitBeforeGettingNackedAgain)368 TEST_F(OutstandingDataTest, MustRetransmitBeforeGettingNackedAgain) {
369 // This test case verifies that a chunk that has been nacked, and scheduled to
370 // be retransmitted, doesn't get nacked again until it has been actually sent
371 // on the wire.
372
373 static constexpr MaxRetransmits kOneRetransmission(1);
374 for (int tsn = 10; tsn <= 20; ++tsn) {
375 buf_.Insert(gen_.Ordered({1}, tsn == 10 ? "B"
376 : tsn == 20 ? "E"
377 : ""),
378 kNow, kOneRetransmission);
379 }
380
381 std::vector<SackChunk::GapAckBlock> gab1 = {SackChunk::GapAckBlock(2, 2)};
382 EXPECT_FALSE(
383 buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab1, false).has_packet_loss);
384 EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
385
386 std::vector<SackChunk::GapAckBlock> gab2 = {SackChunk::GapAckBlock(2, 3)};
387 EXPECT_FALSE(
388 buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab2, false).has_packet_loss);
389 EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
390
391 std::vector<SackChunk::GapAckBlock> gab3 = {SackChunk::GapAckBlock(2, 4)};
392 OutstandingData::AckInfo ack =
393 buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab3, false);
394 EXPECT_TRUE(ack.has_packet_loss);
395 EXPECT_TRUE(buf_.has_data_to_be_retransmitted());
396
397 // Don't call GetChunksToBeRetransmitted yet - simulate that the congestion
398 // window doesn't allow it to be retransmitted yet. It does however get more
399 // SACKs indicating packet loss.
400
401 std::vector<SackChunk::GapAckBlock> gab4 = {SackChunk::GapAckBlock(2, 5)};
402 EXPECT_FALSE(
403 buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab4, false).has_packet_loss);
404 EXPECT_TRUE(buf_.has_data_to_be_retransmitted());
405
406 std::vector<SackChunk::GapAckBlock> gab5 = {SackChunk::GapAckBlock(2, 6)};
407 EXPECT_FALSE(
408 buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab5, false).has_packet_loss);
409 EXPECT_TRUE(buf_.has_data_to_be_retransmitted());
410
411 std::vector<SackChunk::GapAckBlock> gab6 = {SackChunk::GapAckBlock(2, 7)};
412 OutstandingData::AckInfo ack2 =
413 buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab6, false);
414
415 EXPECT_FALSE(ack2.has_packet_loss);
416 EXPECT_TRUE(buf_.has_data_to_be_retransmitted());
417
418 // Now it's retransmitted.
419 EXPECT_THAT(buf_.GetChunksToBeFastRetransmitted(1000),
420 ElementsAre(Pair(TSN(10), _)));
421 EXPECT_THAT(buf_.GetChunksToBeRetransmitted(1000), IsEmpty());
422
423 // And obviously lost, as it will get NACKed and abandoned.
424 std::vector<SackChunk::GapAckBlock> gab7 = {SackChunk::GapAckBlock(2, 8)};
425 EXPECT_FALSE(
426 buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab7, false).has_packet_loss);
427 EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
428
429 std::vector<SackChunk::GapAckBlock> gab8 = {SackChunk::GapAckBlock(2, 9)};
430 EXPECT_FALSE(
431 buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab8, false).has_packet_loss);
432 EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
433
434 EXPECT_CALL(on_discard_, Call(IsUnordered(false), StreamID(1), MID(42)))
435 .WillOnce(Return(false));
436
437 std::vector<SackChunk::GapAckBlock> gab9 = {SackChunk::GapAckBlock(2, 10)};
438 OutstandingData::AckInfo ack3 =
439 buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab9, false);
440
441 EXPECT_TRUE(ack3.has_packet_loss);
442 EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
443 }
444
TEST_F(OutstandingDataTest,CanAbandonChunksMarkedForFastRetransmit)445 TEST_F(OutstandingDataTest, CanAbandonChunksMarkedForFastRetransmit) {
446 // This test is a bit convoluted, and can't really happen with a well behaving
447 // client, but this was found by fuzzers. This test will verify that a message
448 // that was both marked as "to be fast retransmitted" and "abandoned" at the
449 // same time doesn't cause any consistency issues.
450
451 // Add chunks 10-14, but chunk 11 has zero retransmissions. When chunk 10 and
452 // 11 are NACKed three times, chunk 10 will be marked for retransmission, but
453 // chunk 11 will be abandoned, which also abandons chunk 10, as it's part of
454 // the same message.
455 buf_.Insert(gen_.Ordered({1}, "B"), kNow); // 10
456 buf_.Insert(gen_.Ordered({1}, ""), kNow, MaxRetransmits(0)); // 11
457 buf_.Insert(gen_.Ordered({1}, ""), kNow); // 12
458 buf_.Insert(gen_.Ordered({1}, ""), kNow); // 13
459 buf_.Insert(gen_.Ordered({1}, "E"), kNow); // 14
460
461 // ACK 9, 12
462 std::vector<SackChunk::GapAckBlock> gab1 = {SackChunk::GapAckBlock(3, 3)};
463 EXPECT_FALSE(
464 buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab1, false).has_packet_loss);
465 EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
466
467 // ACK 9, 12, 13
468 std::vector<SackChunk::GapAckBlock> gab2 = {SackChunk::GapAckBlock(3, 4)};
469 EXPECT_FALSE(
470 buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab2, false).has_packet_loss);
471 EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
472
473 EXPECT_CALL(on_discard_, Call(IsUnordered(false), StreamID(1), MID(42)))
474 .WillOnce(Return(false));
475
476 // ACK 9, 12, 13, 14
477 std::vector<SackChunk::GapAckBlock> gab3 = {SackChunk::GapAckBlock(3, 5)};
478 OutstandingData::AckInfo ack =
479 buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab3, false);
480 EXPECT_TRUE(ack.has_packet_loss);
481 EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
482 EXPECT_THAT(buf_.GetChunksToBeFastRetransmitted(1000), IsEmpty());
483 EXPECT_THAT(buf_.GetChunksToBeRetransmitted(1000), IsEmpty());
484 }
485
TEST_F(OutstandingDataTest,LifecyleReturnsAckedItemsInAckInfo)486 TEST_F(OutstandingDataTest, LifecyleReturnsAckedItemsInAckInfo) {
487 buf_.Insert(gen_.Ordered({1}, "BE"), kNow, MaxRetransmits::NoLimit(),
488 TimeMs::InfiniteFuture(), LifecycleId(42));
489 buf_.Insert(gen_.Ordered({1}, "BE"), kNow, MaxRetransmits::NoLimit(),
490 TimeMs::InfiniteFuture(), LifecycleId(43));
491 buf_.Insert(gen_.Ordered({1}, "BE"), kNow, MaxRetransmits::NoLimit(),
492 TimeMs::InfiniteFuture(), LifecycleId(44));
493
494 OutstandingData::AckInfo ack1 =
495 buf_.HandleSack(unwrapper_.Unwrap(TSN(11)), {}, false);
496
497 EXPECT_THAT(ack1.acked_lifecycle_ids,
498 ElementsAre(LifecycleId(42), LifecycleId(43)));
499
500 OutstandingData::AckInfo ack2 =
501 buf_.HandleSack(unwrapper_.Unwrap(TSN(12)), {}, false);
502
503 EXPECT_THAT(ack2.acked_lifecycle_ids, ElementsAre(LifecycleId(44)));
504 }
505
TEST_F(OutstandingDataTest,LifecycleReturnsAbandonedNackedThreeTimes)506 TEST_F(OutstandingDataTest, LifecycleReturnsAbandonedNackedThreeTimes) {
507 buf_.Insert(gen_.Ordered({1}, "B"), kNow, MaxRetransmits(0));
508 buf_.Insert(gen_.Ordered({1}, ""), kNow, MaxRetransmits(0));
509 buf_.Insert(gen_.Ordered({1}, ""), kNow, MaxRetransmits(0));
510 buf_.Insert(gen_.Ordered({1}, "E"), kNow, MaxRetransmits(0),
511 TimeMs::InfiniteFuture(), LifecycleId(42));
512
513 std::vector<SackChunk::GapAckBlock> gab1 = {SackChunk::GapAckBlock(2, 2)};
514 EXPECT_FALSE(
515 buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab1, false).has_packet_loss);
516 EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
517
518 std::vector<SackChunk::GapAckBlock> gab2 = {SackChunk::GapAckBlock(2, 3)};
519 EXPECT_FALSE(
520 buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab2, false).has_packet_loss);
521 EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
522
523 std::vector<SackChunk::GapAckBlock> gab3 = {SackChunk::GapAckBlock(2, 4)};
524 EXPECT_CALL(on_discard_, Call(IsUnordered(false), StreamID(1), MID(42)))
525 .WillOnce(Return(false));
526 OutstandingData::AckInfo ack1 =
527 buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab3, false);
528 EXPECT_TRUE(ack1.has_packet_loss);
529 EXPECT_THAT(ack1.abandoned_lifecycle_ids, IsEmpty());
530
531 // This will generate a FORWARD-TSN, which is acked
532 EXPECT_TRUE(buf_.ShouldSendForwardTsn());
533 ForwardTsnChunk chunk = buf_.CreateForwardTsn();
534 EXPECT_EQ(chunk.new_cumulative_tsn(), TSN(13));
535
536 OutstandingData::AckInfo ack2 =
537 buf_.HandleSack(unwrapper_.Unwrap(TSN(13)), {}, false);
538 EXPECT_FALSE(ack2.has_packet_loss);
539 EXPECT_THAT(ack2.abandoned_lifecycle_ids, ElementsAre(LifecycleId(42)));
540 }
541
TEST_F(OutstandingDataTest,LifecycleReturnsAbandonedAfterT3rtxExpired)542 TEST_F(OutstandingDataTest, LifecycleReturnsAbandonedAfterT3rtxExpired) {
543 buf_.Insert(gen_.Ordered({1}, "B"), kNow, MaxRetransmits(0));
544 buf_.Insert(gen_.Ordered({1}, ""), kNow, MaxRetransmits(0));
545 buf_.Insert(gen_.Ordered({1}, ""), kNow, MaxRetransmits(0));
546 buf_.Insert(gen_.Ordered({1}, "E"), kNow, MaxRetransmits(0),
547 TimeMs::InfiniteFuture(), LifecycleId(42));
548
549 EXPECT_THAT(buf_.GetChunkStatesForTesting(),
550 testing::ElementsAre(Pair(TSN(9), State::kAcked), //
551 Pair(TSN(10), State::kInFlight), //
552 Pair(TSN(11), State::kInFlight), //
553 Pair(TSN(12), State::kInFlight), //
554 Pair(TSN(13), State::kInFlight)));
555
556 std::vector<SackChunk::GapAckBlock> gab1 = {SackChunk::GapAckBlock(2, 4)};
557 EXPECT_FALSE(
558 buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab1, false).has_packet_loss);
559 EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
560
561 EXPECT_THAT(buf_.GetChunkStatesForTesting(),
562 testing::ElementsAre(Pair(TSN(9), State::kAcked), //
563 Pair(TSN(10), State::kNacked), //
564 Pair(TSN(11), State::kAcked), //
565 Pair(TSN(12), State::kAcked), //
566 Pair(TSN(13), State::kAcked)));
567
568 // T3-rtx triggered.
569 EXPECT_CALL(on_discard_, Call(IsUnordered(false), StreamID(1), MID(42)))
570 .WillOnce(Return(false));
571 buf_.NackAll();
572
573 EXPECT_THAT(buf_.GetChunkStatesForTesting(),
574 testing::ElementsAre(Pair(TSN(9), State::kAcked), //
575 Pair(TSN(10), State::kAbandoned), //
576 Pair(TSN(11), State::kAbandoned), //
577 Pair(TSN(12), State::kAbandoned), //
578 Pair(TSN(13), State::kAbandoned)));
579
580 // This will generate a FORWARD-TSN, which is acked
581 EXPECT_TRUE(buf_.ShouldSendForwardTsn());
582 ForwardTsnChunk chunk = buf_.CreateForwardTsn();
583 EXPECT_EQ(chunk.new_cumulative_tsn(), TSN(13));
584
585 OutstandingData::AckInfo ack2 =
586 buf_.HandleSack(unwrapper_.Unwrap(TSN(13)), {}, false);
587 EXPECT_FALSE(ack2.has_packet_loss);
588 EXPECT_THAT(ack2.abandoned_lifecycle_ids, ElementsAre(LifecycleId(42)));
589 }
590 } // namespace
591 } // namespace dcsctp
592