1
0
mirror of https://github.com/facebookincubator/mvfst.git synced 2025-08-06 22:22:38 +03:00

Refactor d6d pending events into a single struct

Summary: As a drive-by: fixed a bug where I didn't cancel the pending event when timeouts expire.

Reviewed By: mjoras

Differential Revision: D23910767

fbshipit-source-id: 233e590c17a6c6b7a5f4a251bd8f78f6dfae3c0b
This commit is contained in:
Xiaoting Tang
2020-09-25 13:34:43 -07:00
committed by Facebook GitHub Bot
parent a94e54c41d
commit 37cd692593
7 changed files with 37 additions and 29 deletions

View File

@@ -2446,12 +2446,14 @@ void QuicTransportBase::idleTimeoutExpired(bool drain) noexcept {
void QuicTransportBase::d6dProbeTimeoutExpired() noexcept { void QuicTransportBase::d6dProbeTimeoutExpired() noexcept {
VLOG(4) << __func__ << " " << *this; VLOG(4) << __func__ << " " << *this;
FOLLY_MAYBE_UNUSED auto self = sharedGuard(); FOLLY_MAYBE_UNUSED auto self = sharedGuard();
conn_->pendingEvents.d6d.scheduleProbeTimeout = false;
onD6DProbeTimeoutExpired(*conn_); onD6DProbeTimeoutExpired(*conn_);
} }
void QuicTransportBase::d6dRaiseTimeoutExpired() noexcept { void QuicTransportBase::d6dRaiseTimeoutExpired() noexcept {
VLOG(4) << __func__ << " " << *this; VLOG(4) << __func__ << " " << *this;
FOLLY_MAYBE_UNUSED auto self = sharedGuard(); FOLLY_MAYBE_UNUSED auto self = sharedGuard();
conn_->pendingEvents.d6d.scheduleRaiseTimeout = false;
onD6DRaiseTimeoutExpired(*conn_); onD6DRaiseTimeoutExpired(*conn_);
} }
@@ -2530,7 +2532,7 @@ void QuicTransportBase::schedulePathValidationTimeout() {
} }
void QuicTransportBase::scheduleD6DProbeTimeout() { void QuicTransportBase::scheduleD6DProbeTimeout() {
if (conn_->pendingEvents.scheduleD6DProbeTimeout) { if (conn_->pendingEvents.d6d.scheduleProbeTimeout) {
if (!d6dProbeTimeout_.isScheduled()) { if (!d6dProbeTimeout_.isScheduled()) {
VLOG(10) << __func__ << "timeout=" << conn_->d6d.probeTimeout.count() VLOG(10) << __func__ << "timeout=" << conn_->d6d.probeTimeout.count()
<< "ms " << *this; << "ms " << *this;
@@ -2546,7 +2548,7 @@ void QuicTransportBase::scheduleD6DProbeTimeout() {
} }
void QuicTransportBase::scheduleD6DRaiseTimeout() { void QuicTransportBase::scheduleD6DRaiseTimeout() {
if (conn_->pendingEvents.scheduleD6DRaiseTimeout) { if (conn_->pendingEvents.d6d.scheduleRaiseTimeout) {
if (!d6dRaiseTimeout_.isScheduled()) { if (!d6dRaiseTimeout_.isScheduled()) {
VLOG(10) << __func__ << "timeout=" << conn_->d6d.raiseTimeout.count() VLOG(10) << __func__ << "timeout=" << conn_->d6d.raiseTimeout.count()
<< "s " << *this; << "s " << *this;

View File

@@ -1343,7 +1343,7 @@ uint64_t writeD6DProbeToSocket(
const Aead& aead, const Aead& aead,
const PacketNumberCipher& headerCipher, const PacketNumberCipher& headerCipher,
QuicVersion version) { QuicVersion version) {
if (!connection.pendingEvents.sendD6DProbePacket) { if (!connection.pendingEvents.d6d.sendProbePacket) {
return 0; return 0;
} }
auto builder = ShortHeaderBuilder(); auto builder = ShortHeaderBuilder();
@@ -1373,7 +1373,7 @@ uint64_t writeD6DProbeToSocket(
<< " writing d6d probes using scheduler=D6DScheduler" << " writing d6d probes using scheduler=D6DScheduler"
<< connection; << connection;
if (written > 0) { if (written > 0) {
connection.pendingEvents.sendD6DProbePacket = false; connection.pendingEvents.d6d.sendProbePacket = false;
} }
return written; return written;
} }

View File

@@ -2526,7 +2526,7 @@ TEST_F(QuicTransportFunctionsTest, WriteD6DProbesWithInplaceBuilder) {
auto conn = createConn(); auto conn = createConn();
conn->transportSettings.dataPathType = DataPathType::ContinuousMemory; conn->transportSettings.dataPathType = DataPathType::ContinuousMemory;
conn->d6d.currentProbeSize = 1450; conn->d6d.currentProbeSize = 1450;
conn->pendingEvents.sendD6DProbePacket = true; conn->pendingEvents.d6d.sendProbePacket = true;
auto simpleBufAccessor = auto simpleBufAccessor =
std::make_unique<SimpleBufAccessor>(kDefaultMaxUDPPayload * 16); std::make_unique<SimpleBufAccessor>(kDefaultMaxUDPPayload * 16);
auto outputBuf = simpleBufAccessor->obtain(); auto outputBuf = simpleBufAccessor->obtain();

View File

@@ -40,7 +40,7 @@ void onD6DRaiseTimeoutExpired(QuicConnectionStateBase& conn) {
auto& d6d = conn.d6d; auto& d6d = conn.d6d;
if (d6d.state == D6DMachineState::SEARCH_COMPLETE) { if (d6d.state == D6DMachineState::SEARCH_COMPLETE) {
d6d.state = D6DMachineState::SEARCHING; d6d.state = D6DMachineState::SEARCHING;
conn.pendingEvents.sendD6DProbePacket = true; conn.pendingEvents.d6d.sendProbePacket = true;
} else { } else {
LOG(ERROR) << "d6d: raise timeout expired in state: " LOG(ERROR) << "d6d: raise timeout expired in state: "
<< toString(d6d.state); << toString(d6d.state);
@@ -62,7 +62,7 @@ void onD6DLastProbeAcked(QuicConnectionStateBase& conn) {
CHECK(maybeNextProbeSize.hasValue()); CHECK(maybeNextProbeSize.hasValue());
d6d.currentProbeSize = *maybeNextProbeSize; d6d.currentProbeSize = *maybeNextProbeSize;
d6d.state = D6DMachineState::SEARCHING; d6d.state = D6DMachineState::SEARCHING;
conn.pendingEvents.sendD6DProbePacket = true; conn.pendingEvents.d6d.sendProbePacket = true;
break; break;
case D6DMachineState::SEARCHING: case D6DMachineState::SEARCHING:
CHECK_GT(lastProbeSize, conn.udpSendPacketLen); CHECK_GT(lastProbeSize, conn.udpSendPacketLen);
@@ -74,8 +74,8 @@ void onD6DLastProbeAcked(QuicConnectionStateBase& conn) {
// raiser's internal upper bound, in both cases the search is // raiser's internal upper bound, in both cases the search is
// completed // completed
d6d.state = D6DMachineState::SEARCH_COMPLETE; d6d.state = D6DMachineState::SEARCH_COMPLETE;
conn.pendingEvents.scheduleD6DRaiseTimeout = true; conn.pendingEvents.d6d.scheduleRaiseTimeout = true;
conn.pendingEvents.scheduleD6DProbeTimeout = false; conn.pendingEvents.d6d.scheduleProbeTimeout = false;
} }
break; break;
case D6DMachineState::ERROR: case D6DMachineState::ERROR:
@@ -104,24 +104,24 @@ void onD6DLastProbeLost(QuicConnectionStateBase& conn) {
// connection prior to this state. // connection prior to this state.
} }
// In both BASE and ERROR state, we need to keep sending probes // In both BASE and ERROR state, we need to keep sending probes
conn.pendingEvents.sendD6DProbePacket = true; conn.pendingEvents.d6d.sendProbePacket = true;
break; break;
case D6DMachineState::SEARCHING: case D6DMachineState::SEARCHING:
if (d6d.outstandingProbes >= kDefaultD6DMaxOutstandingProbes) { if (d6d.outstandingProbes >= kDefaultD6DMaxOutstandingProbes) {
// We've lost enough consecutive probes, which should indicate // We've lost enough consecutive probes, which should indicate
// that the upper bound is reached // that the upper bound is reached
d6d.state = D6DMachineState::SEARCH_COMPLETE; d6d.state = D6DMachineState::SEARCH_COMPLETE;
conn.pendingEvents.scheduleD6DRaiseTimeout = true; conn.pendingEvents.d6d.scheduleRaiseTimeout = true;
return; return;
} }
// Otherwise, the loss could be due to congestion, so we keep // Otherwise, the loss could be due to congestion, so we keep
// sending probe // sending probe
// TODO: pace d6d probing when there's congestion // TODO: pace d6d probing when there's congestion
conn.pendingEvents.sendD6DProbePacket = true; conn.pendingEvents.d6d.sendProbePacket = true;
break; break;
case D6DMachineState::ERROR: case D6DMachineState::ERROR:
// Keep probing with min probe size // Keep probing with min probe size
conn.pendingEvents.sendD6DProbePacket = true; conn.pendingEvents.d6d.sendProbePacket = true;
break; break;
default: default:
LOG(ERROR) << "d6d: probe timeout expired in state: " LOG(ERROR) << "d6d: probe timeout expired in state: "
@@ -161,7 +161,7 @@ void detectPMTUBlackhole(
conn.udpSendPacketLen = d6d.basePMTU; conn.udpSendPacketLen = d6d.basePMTU;
// Cancel existing raise timeout if any // Cancel existing raise timeout if any
conn.pendingEvents.scheduleD6DRaiseTimeout = false; conn.pendingEvents.d6d.scheduleRaiseTimeout = false;
} }
} }
} // namespace quic } // namespace quic

View File

@@ -50,11 +50,11 @@ class QuicD6DStateFunctionsTest : public Test {
conn.d6d.state = fixture.stateBegin; conn.d6d.state = fixture.stateBegin;
conn.d6d.outstandingProbes = fixture.outstandingProbes; conn.d6d.outstandingProbes = fixture.outstandingProbes;
conn.d6d.currentProbeSize = fixture.currentProbeSizeBegin; conn.d6d.currentProbeSize = fixture.currentProbeSizeBegin;
conn.pendingEvents.sendD6DProbePacket = fixture.sendProbeBegin; conn.pendingEvents.d6d.sendProbePacket = fixture.sendProbeBegin;
onD6DLastProbeLost(conn); onD6DLastProbeLost(conn);
EXPECT_EQ(conn.d6d.state, fixture.stateEnd); EXPECT_EQ(conn.d6d.state, fixture.stateEnd);
EXPECT_EQ(conn.d6d.currentProbeSize, fixture.currentProbeSizeEnd); EXPECT_EQ(conn.d6d.currentProbeSize, fixture.currentProbeSizeEnd);
EXPECT_EQ(conn.pendingEvents.sendD6DProbePacket, fixture.sendProbeEnd); EXPECT_EQ(conn.pendingEvents.d6d.sendProbePacket, fixture.sendProbeEnd);
} }
}; };

View File

@@ -280,7 +280,7 @@ void QuicServerTransport::writeData() {
packetLimit); packetLimit);
// D6D probes should be paced // D6D probes should be paced
if (packetLimit && conn_->pendingEvents.sendD6DProbePacket) { if (packetLimit && conn_->pendingEvents.d6d.sendProbePacket) {
writeD6DProbeToSocket( writeD6DProbeToSocket(
*socket_, *socket_,
*conn_, *conn_,
@@ -540,7 +540,7 @@ void QuicServerTransport::maybeStartD6DProbing() {
if (self->closeState_ == CloseState::CLOSED) { if (self->closeState_ == CloseState::CLOSED) {
return; return;
} }
self->conn_->pendingEvents.sendD6DProbePacket = true; self->conn_->pendingEvents.d6d.sendProbePacket = true;
}, },
kDefaultD6DKickStartDelay.count()); kDefaultD6DKickStartDelay.count());
} }

View File

@@ -606,6 +606,20 @@ struct QuicConnectionStateBase : public folly::DelayedDestruction {
// Whether or not we received a new packet before a write. // Whether or not we received a new packet before a write.
bool receivedNewPacketBeforeWrite{false}; bool receivedNewPacketBeforeWrite{false};
// D6D related events
struct PendingD6DEvents {
// If we should schedule/cancel d6d raise timeout, if it's not
// already scheduled/canceled
bool scheduleRaiseTimeout{false};
// If we should schedule/cancel d6d probe timeout, if it's not
// already scheduled/canceled
bool scheduleProbeTimeout{false};
// To send a d6d probe packet
bool sendProbePacket{false};
};
struct PendingEvents { struct PendingEvents {
Resets resets; Resets resets;
@@ -620,14 +634,6 @@ struct QuicConnectionStateBase : public folly::DelayedDestruction {
// If we should schedule a new Ack timeout, if it's not already scheduled // If we should schedule a new Ack timeout, if it's not already scheduled
bool scheduleAckTimeout{false}; bool scheduleAckTimeout{false};
// If we should schedule/cancel d6d raise timeout, if it's not
// already scheduled/canceled
bool scheduleD6DRaiseTimeout{false};
// If we should schedule/cancel d6d probe timeout, if it's not
// already scheduled/canceled
bool scheduleD6DProbeTimeout{false};
// Whether a connection level window update is due to send // Whether a connection level window update is due to send
bool connWindowUpdate{false}; bool connWindowUpdate{false};
@@ -645,12 +651,12 @@ struct QuicConnectionStateBase : public folly::DelayedDestruction {
// To send a ping frame // To send a ping frame
bool sendPing{false}; bool sendPing{false};
// To send a d6d probe packet
bool sendD6DProbePacket{false};
// Do we need to send data blocked frame when connection is blocked. // Do we need to send data blocked frame when connection is blocked.
bool sendDataBlocked{false}; bool sendDataBlocked{false};
// D6D related events
PendingD6DEvents d6d;
std::vector<KnobFrame> knobs; std::vector<KnobFrame> knobs;
}; };