Skip to content

Commit 7f65f36

Browse files
jbeshayfacebook-github-bot
authored andcommitted
Cache the negotiated config for ACKs once the transport parameters are received
Summary: Cache the negotiated config for what ACK type to write and which fields to use once the peer transport parameters are available. This avoids computing the config with every ack frame being written. Reviewed By: sharmafb Differential Revision: D70004436 fbshipit-source-id: 79354f5137c77353c3a97d4c41782a700622e986
1 parent c6d8f76 commit 7f65f36

File tree

7 files changed

+56
-23
lines changed

7 files changed

+56
-23
lines changed

quic/api/QuicAckScheduler.cpp

Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -63,32 +63,13 @@ Optional<PacketNum> AckScheduler::writeNextAcks(
6363

6464
Optional<WriteAckFrameResult> ackWriteResult;
6565

66-
bool isAckReceiveTimestampsSupported =
67-
conn_.transportSettings.maybeAckReceiveTimestampsConfigSentToPeer &&
68-
conn_.maybePeerAckReceiveTimestampsConfig;
69-
7066
uint64_t peerRequestedTimestampsCount =
7167
conn_.maybePeerAckReceiveTimestampsConfig.has_value()
7268
? conn_.maybePeerAckReceiveTimestampsConfig.value()
7369
.maxReceiveTimestampsPerAck
7470
: 0;
7571

76-
uint64_t extendedAckSupportedAndEnabled =
77-
conn_.peerAdvertisedExtendedAckFeatures &
78-
conn_.transportSettings.enableExtendedAckFeatures;
79-
// Disable the ECN fields if we are not reading them
80-
if (!conn_.transportSettings.readEcnOnIngress) {
81-
extendedAckSupportedAndEnabled &= ~static_cast<ExtendedAckFeatureMaskType>(
82-
ExtendedAckFeatureMask::ECN_COUNTS);
83-
}
84-
// Disable the receive timestamps fields if we have not regoatiated receive
85-
// timestamps support
86-
if (!isAckReceiveTimestampsSupported || (peerRequestedTimestampsCount == 0)) {
87-
extendedAckSupportedAndEnabled &= ~static_cast<ExtendedAckFeatureMaskType>(
88-
ExtendedAckFeatureMask::RECEIVE_TIMESTAMPS);
89-
}
90-
91-
if (extendedAckSupportedAndEnabled > 0) {
72+
if (conn_.negotiatedExtendedAckFeatures > 0) {
9273
// The peer supports extended ACKs and we have them enabled.
9374
ackWriteResult = writeAckFrame(
9475
meta,
@@ -97,7 +78,7 @@ Optional<PacketNum> AckScheduler::writeNextAcks(
9778
conn_.transportSettings.maybeAckReceiveTimestampsConfigSentToPeer
9879
.value_or(AckReceiveTimestampsConfig()),
9980
peerRequestedTimestampsCount,
100-
extendedAckSupportedAndEnabled);
81+
conn_.negotiatedExtendedAckFeatures);
10182
} else if (
10283
conn_.transportSettings.readEcnOnIngress &&
10384
(meta.ackState.ecnECT0CountReceived ||
@@ -107,8 +88,7 @@ Optional<PacketNum> AckScheduler::writeNextAcks(
10788
// frame. In this case, we give ACK_ECN precedence over
10889
// ACK_RECEIVE_TIMESTAMPS.
10990
ackWriteResult = writeAckFrame(meta, builder, FrameType::ACK_ECN);
110-
} else if (
111-
isAckReceiveTimestampsSupported && (peerRequestedTimestampsCount > 0)) {
91+
} else if (conn_.negotiatedAckReceiveTimestampSupport) {
11292
// Use ACK_RECEIVE_TIMESTAMPS if its enabled on both endpoints AND the
11393
// peer requests at least 1 timestamp
11494
ackWriteResult = writeAckFrame(

quic/api/QuicTransportFunctions.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2131,4 +2131,35 @@ void maybeScheduleAckForCongestionFeedback(
21312131
}
21322132
}
21332133

2134+
void updateNegotiatedAckFeatures(QuicConnectionStateBase& conn) {
2135+
bool isAckReceiveTimestampsSupported =
2136+
conn.transportSettings.maybeAckReceiveTimestampsConfigSentToPeer &&
2137+
conn.maybePeerAckReceiveTimestampsConfig;
2138+
2139+
uint64_t peerRequestedTimestampsCount =
2140+
conn.maybePeerAckReceiveTimestampsConfig.has_value()
2141+
? conn.maybePeerAckReceiveTimestampsConfig.value()
2142+
.maxReceiveTimestampsPerAck
2143+
: 0;
2144+
2145+
conn.negotiatedAckReceiveTimestampSupport =
2146+
isAckReceiveTimestampsSupported && (peerRequestedTimestampsCount > 0);
2147+
2148+
conn.negotiatedExtendedAckFeatures = conn.peerAdvertisedExtendedAckFeatures &
2149+
conn.transportSettings.enableExtendedAckFeatures;
2150+
// Disable the ECN fields if we are not reading them
2151+
if (!conn.transportSettings.readEcnOnIngress) {
2152+
conn.negotiatedExtendedAckFeatures &=
2153+
~static_cast<ExtendedAckFeatureMaskType>(
2154+
ExtendedAckFeatureMask::ECN_COUNTS);
2155+
}
2156+
// Disable the receive timestamps fields if we have not regoatiated receive
2157+
// timestamps support
2158+
if (!conn.negotiatedAckReceiveTimestampSupport) {
2159+
conn.negotiatedExtendedAckFeatures &=
2160+
~static_cast<ExtendedAckFeatureMaskType>(
2161+
ExtendedAckFeatureMask::RECEIVE_TIMESTAMPS);
2162+
}
2163+
}
2164+
21342165
} // namespace quic

quic/api/QuicTransportFunctions.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,4 +345,5 @@ void maybeAddPacketMark(
345345
void maybeScheduleAckForCongestionFeedback(
346346
const ReceivedUdpPacket& receivedPacket,
347347
AckState& ackState);
348+
void updateNegotiatedAckFeatures(QuicConnectionStateBase& conn);
348349
} // namespace quic

quic/api/test/QuicPacketSchedulerTest.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2816,6 +2816,7 @@ TEST_F(QuicAckSchedulerTest, WriteAckReceiveTimestampsWhenEnabled) {
28162816
conn_->transportSettings.maybeAckReceiveTimestampsConfigSentToPeer =
28172817
AckReceiveTimestampsConfig();
28182818

2819+
updateNegotiatedAckFeatures(*conn_);
28192820
AckScheduler ackScheduler(*conn_, ackState_);
28202821
ASSERT_TRUE(ackScheduler.hasPendingAcks());
28212822

@@ -2874,6 +2875,7 @@ TEST_F(QuicAckSchedulerTest, AckExtendedNotSentIfNotSupported) {
28742875
conn_->transportSettings.enableExtendedAckFeatures =
28752876
3; // ECN + ReceiveTimestamps
28762877
conn_->peerAdvertisedExtendedAckFeatures = 0;
2878+
updateNegotiatedAckFeatures(*conn_);
28772879

28782880
AckScheduler ackScheduler(*conn_, ackState_);
28792881
ASSERT_TRUE(ackScheduler.hasPendingAcks());
@@ -2902,6 +2904,7 @@ TEST_F(QuicAckSchedulerTest, AckExtendedNotSentIfNotEnabled) {
29022904

29032905
conn_->transportSettings.enableExtendedAckFeatures = 0;
29042906
conn_->peerAdvertisedExtendedAckFeatures = 3; // ECN + ReceiveTimestamps;
2907+
updateNegotiatedAckFeatures(*conn_);
29052908

29062909
AckScheduler ackScheduler(*conn_, ackState_);
29072910
ASSERT_TRUE(ackScheduler.hasPendingAcks());
@@ -2938,6 +2941,7 @@ TEST_F(
29382941
conn_->maybePeerAckReceiveTimestampsConfig = AckReceiveTimestampsConfig();
29392942
// We don't have an ART config (i.e. we can't sent ART)
29402943
conn_->transportSettings.maybeAckReceiveTimestampsConfigSentToPeer = none;
2944+
updateNegotiatedAckFeatures(*conn_);
29412945

29422946
AckScheduler ackScheduler(*conn_, ackState_);
29432947
ASSERT_TRUE(ackScheduler.hasPendingAcks());
@@ -2972,6 +2976,8 @@ TEST_F(QuicAckSchedulerTest, AckExtendedNotSentIfECNFeatureNotSupported) {
29722976
conn_->transportSettings.maybeAckReceiveTimestampsConfigSentToPeer =
29732977
AckReceiveTimestampsConfig();
29742978

2979+
updateNegotiatedAckFeatures(*conn_);
2980+
29752981
AckScheduler ackScheduler(*conn_, ackState_);
29762982
ASSERT_TRUE(ackScheduler.hasPendingAcks());
29772983

@@ -3009,6 +3015,8 @@ TEST_F(QuicAckSchedulerTest, AckExtendedWithAllFeatures) {
30093015
// We can read ECN
30103016
conn_->transportSettings.readEcnOnIngress = true;
30113017

3018+
updateNegotiatedAckFeatures(*conn_);
3019+
30123020
AckScheduler ackScheduler(*conn_, ackState_);
30133021
ASSERT_TRUE(ackScheduler.hasPendingAcks());
30143022

@@ -3046,6 +3054,8 @@ TEST_F(QuicAckSchedulerTest, AckExtendedTakesPrecedenceOverECN) {
30463054
// We can read ECN
30473055
conn_->transportSettings.readEcnOnIngress = true;
30483056

3057+
updateNegotiatedAckFeatures(*conn_);
3058+
30493059
AckScheduler ackScheduler(*conn_, ackState_);
30503060
ASSERT_TRUE(ackScheduler.hasPendingAcks());
30513061

@@ -3083,6 +3093,8 @@ TEST_F(QuicAckSchedulerTest, AckExtendedTakesPrecedenceOverReceiveTimestamps) {
30833093
// We can read ECN
30843094
conn_->transportSettings.readEcnOnIngress = true;
30853095

3096+
updateNegotiatedAckFeatures(*conn_);
3097+
30863098
AckScheduler ackScheduler(*conn_, ackState_);
30873099
ASSERT_TRUE(ackScheduler.hasPendingAcks());
30883100

quic/client/QuicClientTransportLite.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -798,6 +798,8 @@ void QuicClientTransportLite::processUdpPacketData(
798798
}
799799
}
800800
}
801+
updateNegotiatedAckFeatures(*conn_);
802+
801803
// TODO This sucks, but manually update the max packet size until we fix
802804
// 0-rtt transport parameters.
803805
if (conn_->transportSettings.canIgnorePathMTU &&

quic/server/state/ServerStateMachine.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,7 @@ void updateHandshakeState(QuicServerConnectionState& conn) {
445445
TransportErrorCode::TRANSPORT_PARAMETER_ERROR);
446446
}
447447
processClientInitialParams(conn, std::move(*clientParams));
448+
updateNegotiatedAckFeatures(conn);
448449
}
449450
if (oneRttReadCipher) {
450451
if (conn.qLogger) {

quic/state/StateData.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -705,6 +705,12 @@ struct QuicConnectionStateBase : public folly::DelayedDestruction {
705705
bool peerAdvertisedKnobFrameSupport{false};
706706

707707
ExtendedAckFeatureMaskType peerAdvertisedExtendedAckFeatures{0};
708+
709+
// Negotiated ACK related config. These don't change throughout the connection
710+
// so cache them once we've receive the relevant transport parameters.
711+
bool negotiatedAckReceiveTimestampSupport{false};
712+
ExtendedAckFeatureMaskType negotiatedExtendedAckFeatures{0};
713+
708714
// Retransmission policies map.
709715
folly::F14FastMap<StreamGroupId, QuicStreamGroupRetransmissionPolicy>
710716
retransmissionPolicies;

0 commit comments

Comments
 (0)