mirror of
https://github.com/facebookincubator/mvfst.git
synced 2025-08-06 22:22:38 +03:00
send d6d probe packets via writeD6DProbingDataToSocket
Summary: This is the transport function that sends d6d probe to socket. It - checks if there's the pending event `sendD6DProbePacket`, which will be set by upon d6d's probe timer expiration. - uses the current probeSize to instantiate a D6DProbeScheduler, which will be changed by a small d6d state machine. Reviewed By: yangchi Differential Revision: D23193967 fbshipit-source-id: dfe6ce831cfd6ff0470e801644b95d4e8da34e87
This commit is contained in:
committed by
Facebook GitHub Bot
parent
23f817100a
commit
1aec6b57f0
@@ -22,6 +22,7 @@ using DurationRep = std::chrono::microseconds::rep;
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
// Default QUIC packet size for both read and write.
|
||||
// TODO(xtt): make them configurable
|
||||
constexpr uint64_t kDefaultV4UDPSendPacketLen = 1252;
|
||||
constexpr uint64_t kDefaultV6UDPSendPacketLen = 1232;
|
||||
// With Android NDK r15c for some apps we use gnu-libstdc++ instead of
|
||||
|
@@ -1341,6 +1341,49 @@ uint64_t writeProbingDataToSocket(
|
||||
return written;
|
||||
}
|
||||
|
||||
uint64_t writeD6DProbeToSocket(
|
||||
folly::AsyncUDPSocket& sock,
|
||||
QuicConnectionStateBase& connection,
|
||||
const ConnectionId& srcConnId,
|
||||
const ConnectionId& dstConnId,
|
||||
const Aead& aead,
|
||||
const PacketNumberCipher& headerCipher,
|
||||
QuicVersion version) {
|
||||
if (!connection.pendingEvents.sendD6DProbePacket) {
|
||||
return 0;
|
||||
}
|
||||
auto builder = ShortHeaderBuilder();
|
||||
// D6D probe is always in AppData pnSpace
|
||||
auto pnSpace = PacketNumberSpace::AppData;
|
||||
// Skip a packet number for probing packets to elicit acks
|
||||
increaseNextPacketNum(connection, pnSpace);
|
||||
D6DProbeScheduler d6dProbeScheduler(
|
||||
connection,
|
||||
"D6DProbeScheduler",
|
||||
aead.getCipherOverhead(),
|
||||
connection.d6d.currentProbeSize);
|
||||
auto written = writeConnectionDataToSocket(
|
||||
sock,
|
||||
connection,
|
||||
srcConnId,
|
||||
dstConnId,
|
||||
builder,
|
||||
pnSpace,
|
||||
d6dProbeScheduler,
|
||||
unlimitedWritableBytes,
|
||||
1,
|
||||
aead,
|
||||
headerCipher,
|
||||
version);
|
||||
VLOG_IF(10, written > 0) << nodeToString(connection.nodeType)
|
||||
<< " writing d6d probes using scheduler=D6DScheduler"
|
||||
<< connection;
|
||||
if (written > 0) {
|
||||
connection.pendingEvents.sendD6DProbePacket = false;
|
||||
}
|
||||
return written;
|
||||
}
|
||||
|
||||
WriteDataReason shouldWriteData(const QuicConnectionStateBase& conn) {
|
||||
if (conn.pendingEvents.numProbePackets) {
|
||||
VLOG(10) << nodeToString(conn.nodeType) << " needs write because of PTO"
|
||||
|
@@ -282,6 +282,15 @@ uint64_t writeProbingDataToSocket(
|
||||
QuicVersion version,
|
||||
const std::string& token = std::string());
|
||||
|
||||
uint64_t writeD6DProbeToSocket(
|
||||
folly::AsyncUDPSocket& sock,
|
||||
QuicConnectionStateBase& connection,
|
||||
const ConnectionId& srcConnId,
|
||||
const ConnectionId& dstConnId,
|
||||
const Aead& aead,
|
||||
const PacketNumberCipher& headerCipher,
|
||||
QuicVersion version);
|
||||
|
||||
HeaderBuilder LongHeaderBuilder(LongHeader::Types packetType);
|
||||
HeaderBuilder ShortHeaderBuilder();
|
||||
|
||||
|
@@ -2519,5 +2519,42 @@ TEST_F(QuicTransportFunctionsTest, WriteProbingWithInplaceBuilder) {
|
||||
EXPECT_EQ(conn->outstandings.packets.size(), outstandingPacketsCount + 3);
|
||||
}
|
||||
|
||||
TEST_F(QuicTransportFunctionsTest, WriteD6DProbesWithInplaceBuilder) {
|
||||
auto conn = createConn();
|
||||
conn->transportSettings.dataPathType = DataPathType::ContinuousMemory;
|
||||
conn->d6d.currentProbeSize = 1450;
|
||||
conn->pendingEvents.sendD6DProbePacket = true;
|
||||
auto simpleBufAccessor =
|
||||
std::make_unique<SimpleBufAccessor>(kDefaultMaxUDPPayload * 16);
|
||||
auto outputBuf = simpleBufAccessor->obtain();
|
||||
auto bufPtr = outputBuf.get();
|
||||
simpleBufAccessor->release(std::move(outputBuf));
|
||||
conn->bufAccessor = simpleBufAccessor.get();
|
||||
conn->transportSettings.batchingMode = QuicBatchingMode::BATCHING_MODE_GSO;
|
||||
EventBase evb;
|
||||
folly::test::MockAsyncUDPSocket mockSock(&evb);
|
||||
EXPECT_CALL(mockSock, getGSO()).WillRepeatedly(Return(true));
|
||||
EXPECT_CALL(mockSock, write(_, _))
|
||||
.Times(1)
|
||||
.WillOnce(Invoke([&](const SocketAddress&,
|
||||
const std::unique_ptr<folly::IOBuf>& sockBuf) {
|
||||
EXPECT_EQ(sockBuf->length(), conn->d6d.currentProbeSize);
|
||||
EXPECT_EQ(sockBuf.get(), bufPtr);
|
||||
EXPECT_TRUE(folly::IOBufEqualTo()(*sockBuf, *bufPtr));
|
||||
EXPECT_FALSE(sockBuf->isChained());
|
||||
return sockBuf->computeChainDataLength();
|
||||
}));
|
||||
writeD6DProbeToSocket(
|
||||
mockSock,
|
||||
*conn,
|
||||
*conn->clientConnectionId,
|
||||
*conn->serverConnectionId,
|
||||
*aead,
|
||||
*headerCipher,
|
||||
getVersion(*conn));
|
||||
EXPECT_EQ(0, bufPtr->length());
|
||||
EXPECT_EQ(0, bufPtr->headroom());
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace quic
|
||||
|
@@ -626,6 +626,9 @@ struct QuicConnectionStateBase : public folly::DelayedDestruction {
|
||||
// To send a ping frame
|
||||
bool sendPing{false};
|
||||
|
||||
// To send a d6d probe packet
|
||||
bool sendD6DProbePacket{false};
|
||||
|
||||
// Do we need to send data blocked frame when connection is blocked.
|
||||
bool sendDataBlocked{false};
|
||||
|
||||
@@ -765,6 +768,9 @@ struct QuicConnectionStateBase : public folly::DelayedDestruction {
|
||||
// The base PMTU to start probing with
|
||||
uint16_t basePMTU{kDefaultD6DBasePMTU};
|
||||
|
||||
// Current probe size
|
||||
uint32_t currentProbeSize{kDefaultD6DBasePMTU};
|
||||
|
||||
// The raise timeout
|
||||
std::chrono::seconds raiseTimeout{kDefaultD6DRaiseTimeout};
|
||||
};
|
||||
|
Reference in New Issue
Block a user