mirror of
https://github.com/facebookincubator/mvfst.git
synced 2025-08-09 20:42:44 +03:00
Summary: - Adds counter of the number of ack-eliciting packets sent; useful for understanding lost / retransmission numbers - Adds the following to `OutstandingPacketMetadata` - # of packets sent and # of ack-eliciting packets sent; this enables indexing of each packet when processed by an observer on loss / RTT event, including understanding its ordering in the flow of sent packets. - # of packets in flight; useful during loss analysis to understand if self-induced congestion could be culprit - Fixes the inflightBytes counter in `OutstandingPacketMetadata`; it was previously _not_ including the packets own bytes, despite saying that it was. Right now we are passing multiple integers into the `OutstandingPacket` constructor. I've switched to passing in `LossState` to avoid passing in two more integers, although I will need to come back and clean up the existing ones. Differential Revision: D25861702 fbshipit-source-id: e34c0edcb136bc1a2a6aeb898ecbb4cf11d0aa2c
151 lines
4.3 KiB
C++
151 lines
4.3 KiB
C++
/*
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*
|
|
*/
|
|
|
|
#include <gmock/gmock.h>
|
|
#include <gtest/gtest.h>
|
|
|
|
#include <quic/common/test/TestUtils.h>
|
|
#include <quic/state/StateData.h>
|
|
#include "quic/state/LossState.h"
|
|
|
|
using namespace quic;
|
|
using namespace testing;
|
|
|
|
constexpr QuicVersion kVersion = static_cast<QuicVersion>(0);
|
|
|
|
namespace quic {
|
|
namespace test {
|
|
|
|
class StateDataTest : public Test {};
|
|
|
|
TEST_F(StateDataTest, EmptyLossEvent) {
|
|
CongestionController::LossEvent loss;
|
|
EXPECT_EQ(0, loss.lostBytes);
|
|
EXPECT_FALSE(loss.largestLostPacketNum);
|
|
}
|
|
|
|
TEST_F(StateDataTest, SingleLostPacketEvent) {
|
|
RegularQuicWritePacket packet(LongHeader(
|
|
LongHeader::Types::Initial,
|
|
getTestConnectionId(1),
|
|
getTestConnectionId(),
|
|
100,
|
|
kVersion));
|
|
OutstandingPacket outstandingPacket(
|
|
packet, Clock::now(), 1234, false, 1234, 0, 0, LossState());
|
|
CongestionController::LossEvent loss;
|
|
loss.addLostPacket(outstandingPacket);
|
|
EXPECT_EQ(1234, loss.lostBytes);
|
|
EXPECT_EQ(100, *loss.largestLostPacketNum);
|
|
}
|
|
|
|
TEST_F(StateDataTest, MultipleLostPacketsEvent) {
|
|
RegularQuicWritePacket packet1(LongHeader(
|
|
LongHeader::Types::Initial,
|
|
getTestConnectionId(1),
|
|
getTestConnectionId(),
|
|
100,
|
|
kVersion));
|
|
OutstandingPacket outstandingPacket1(
|
|
packet1, Clock::now(), 1234, false, 1234, 0, 0, LossState());
|
|
|
|
RegularQuicWritePacket packet2(LongHeader(
|
|
LongHeader::Types::Initial,
|
|
getTestConnectionId(1),
|
|
getTestConnectionId(),
|
|
110,
|
|
kVersion));
|
|
OutstandingPacket outstandingPacket2(
|
|
packet2, Clock::now(), 1357, false, 1357, 0, 0, LossState());
|
|
|
|
CongestionController::LossEvent loss;
|
|
loss.addLostPacket(outstandingPacket1);
|
|
loss.addLostPacket(outstandingPacket2);
|
|
EXPECT_EQ(1234 + 1357, loss.lostBytes);
|
|
EXPECT_EQ(110, *loss.largestLostPacketNum);
|
|
}
|
|
|
|
constexpr size_t kRtt{100000};
|
|
|
|
class PendingPathRateLimiterTest : public Test {
|
|
public:
|
|
void SetUp() override {
|
|
now = std::chrono::steady_clock::now();
|
|
}
|
|
|
|
protected:
|
|
QuicConnectionStateBase conn_{QuicNodeType::Server};
|
|
PendingPathRateLimiter limiter_{conn_.udpSendPacketLen};
|
|
size_t maxWindowBytes{kMinCwndInMss * conn_.udpSendPacketLen};
|
|
TimePoint now;
|
|
};
|
|
|
|
TEST_F(PendingPathRateLimiterTest, TestSetInitialCredit) {
|
|
EXPECT_EQ(
|
|
limiter_.currentCredit(now, std::chrono::microseconds{kRtt}),
|
|
maxWindowBytes);
|
|
conn_.udpSendPacketLen = 2000;
|
|
PendingPathRateLimiter limiter2{conn_.udpSendPacketLen};
|
|
EXPECT_EQ(
|
|
limiter2.currentCredit(now, std::chrono::microseconds{kRtt}),
|
|
kMinCwndInMss * 2000);
|
|
}
|
|
|
|
TEST_F(PendingPathRateLimiterTest, TestNoImmediateCreditRefresh) {
|
|
EXPECT_EQ(
|
|
limiter_.currentCredit(now, std::chrono::microseconds{kRtt}),
|
|
maxWindowBytes);
|
|
limiter_.onPacketSent(420);
|
|
EXPECT_EQ(
|
|
limiter_.currentCredit(now, std::chrono::microseconds{kRtt}),
|
|
maxWindowBytes - 420);
|
|
}
|
|
|
|
TEST_F(PendingPathRateLimiterTest, TestBoundaryRttPassedCreditRefresh) {
|
|
EXPECT_EQ(
|
|
limiter_.currentCredit(now, std::chrono::microseconds{kRtt}),
|
|
maxWindowBytes);
|
|
limiter_.onPacketSent(420);
|
|
auto halfRtt = std::chrono::microseconds(kRtt / 2);
|
|
now += halfRtt;
|
|
EXPECT_EQ(
|
|
limiter_.currentCredit(now, std::chrono::microseconds{kRtt}),
|
|
maxWindowBytes - 420);
|
|
limiter_.onPacketSent(420);
|
|
now += halfRtt;
|
|
EXPECT_EQ(
|
|
limiter_.currentCredit(now, std::chrono::microseconds{kRtt}),
|
|
maxWindowBytes - 840);
|
|
|
|
now += std::chrono::microseconds(10);
|
|
EXPECT_EQ(
|
|
limiter_.currentCredit(now, std::chrono::microseconds{kRtt}),
|
|
maxWindowBytes);
|
|
}
|
|
|
|
TEST_F(PendingPathRateLimiterTest, TestCreditRefreshOnInfrequentSends) {
|
|
auto delta =
|
|
std::chrono::microseconds{kRtt} + std::chrono::microseconds{1000};
|
|
EXPECT_EQ(
|
|
limiter_.currentCredit(now, std::chrono::microseconds{kRtt}),
|
|
maxWindowBytes);
|
|
limiter_.onPacketSent(420);
|
|
now += delta;
|
|
EXPECT_EQ(
|
|
limiter_.currentCredit(now, std::chrono::microseconds{kRtt}),
|
|
maxWindowBytes);
|
|
limiter_.onPacketSent(420);
|
|
now += delta;
|
|
EXPECT_EQ(
|
|
limiter_.currentCredit(now, std::chrono::microseconds{kRtt}),
|
|
maxWindowBytes);
|
|
}
|
|
|
|
} // namespace test
|
|
} // namespace quic
|