1
0
mirror of https://github.com/facebookincubator/mvfst.git synced 2025-12-03 03:40:56 +03:00

Always update max packet size after 0-rtt.

Summary: This is a temporary hack until we properly implement 0-rtt transport parameter updating. Now after 0-rtt we will use the packet size from the peer as the max packet size, if the can ignore setting is set.

Reviewed By: xttjsn

Differential Revision: D23690019

fbshipit-source-id: b4dbf5702e81e52ccd437e0fa68f4d156c7123be
This commit is contained in:
Matt Joras
2020-09-15 08:35:45 -07:00
committed by Facebook GitHub Bot
parent 2c377ea5d3
commit 43a0b7e02d
4 changed files with 76 additions and 60 deletions

View File

@@ -10,6 +10,7 @@
#include <folly/portability/Sockets.h> #include <folly/portability/Sockets.h>
#include <quic/QuicConstants.h>
#include <quic/api/LoopDetectorCallback.h> #include <quic/api/LoopDetectorCallback.h>
#include <quic/api/QuicTransportFunctions.h> #include <quic/api/QuicTransportFunctions.h>
#include <quic/client/handshake/ClientHandshakeFactory.h> #include <quic/client/handshake/ClientHandshakeFactory.h>
@@ -531,72 +532,89 @@ void QuicClientTransport::processPacketData(
// We should get transport parameters if we've derived 1-rtt keys and 0-rtt // We should get transport parameters if we've derived 1-rtt keys and 0-rtt
// was rejected, or we have derived 1-rtt keys and 0-rtt was never // was rejected, or we have derived 1-rtt keys and 0-rtt was never
// attempted. // attempted.
if ((oneRttKeyDerivationTriggered && if (oneRttKeyDerivationTriggered) {
((zeroRttRejected.has_value() && *zeroRttRejected) ||
!zeroRttRejected.has_value()))) {
auto originalPeerMaxOffset =
conn_->flowControlState.peerAdvertisedMaxOffset;
auto originalPeerInitialStreamOffsetBidiLocal =
conn_->flowControlState.peerAdvertisedInitialMaxStreamOffsetBidiLocal;
auto originalPeerInitialStreamOffsetBidiRemote =
conn_->flowControlState
.peerAdvertisedInitialMaxStreamOffsetBidiRemote;
auto originalPeerInitialStreamOffsetUni =
conn_->flowControlState.peerAdvertisedInitialMaxStreamOffsetUni;
VLOG(10) << "Client negotiated transport params " << *this;
auto serverParams = handshakeLayer->getServerTransportParams(); auto serverParams = handshakeLayer->getServerTransportParams();
if (!serverParams) { if (!serverParams) {
throw QuicTransportException( throw QuicTransportException(
"No server transport params", "No server transport params",
TransportErrorCode::TRANSPORT_PARAMETER_ERROR); TransportErrorCode::TRANSPORT_PARAMETER_ERROR);
} }
auto maxStreamsBidi = getIntegerParameter( if ((zeroRttRejected.has_value() && *zeroRttRejected) ||
TransportParameterId::initial_max_streams_bidi, !zeroRttRejected.has_value()) {
serverParams->parameters); auto originalPeerMaxOffset =
auto maxStreamsUni = getIntegerParameter( conn_->flowControlState.peerAdvertisedMaxOffset;
TransportParameterId::initial_max_streams_uni, auto originalPeerInitialStreamOffsetBidiLocal =
serverParams->parameters); conn_->flowControlState
processServerInitialParams( .peerAdvertisedInitialMaxStreamOffsetBidiLocal;
*clientConn_, std::move(*serverParams), packetNum); auto originalPeerInitialStreamOffsetBidiRemote =
conn_->flowControlState
.peerAdvertisedInitialMaxStreamOffsetBidiRemote;
auto originalPeerInitialStreamOffsetUni =
conn_->flowControlState.peerAdvertisedInitialMaxStreamOffsetUni;
VLOG(10) << "Client negotiated transport params " << *this;
auto maxStreamsBidi = getIntegerParameter(
TransportParameterId::initial_max_streams_bidi,
serverParams->parameters);
auto maxStreamsUni = getIntegerParameter(
TransportParameterId::initial_max_streams_uni,
serverParams->parameters);
processServerInitialParams(
*clientConn_, std::move(*serverParams), packetNum);
cacheServerInitialParams( cacheServerInitialParams(
*clientConn_, *clientConn_,
conn_->flowControlState.peerAdvertisedMaxOffset, conn_->flowControlState.peerAdvertisedMaxOffset,
conn_->flowControlState.peerAdvertisedInitialMaxStreamOffsetBidiLocal, conn_->flowControlState
conn_->flowControlState .peerAdvertisedInitialMaxStreamOffsetBidiLocal,
.peerAdvertisedInitialMaxStreamOffsetBidiRemote, conn_->flowControlState
conn_->flowControlState.peerAdvertisedInitialMaxStreamOffsetUni, .peerAdvertisedInitialMaxStreamOffsetBidiRemote,
maxStreamsBidi.value_or(0), conn_->flowControlState.peerAdvertisedInitialMaxStreamOffsetUni,
maxStreamsUni.value_or(0)); maxStreamsBidi.value_or(0),
maxStreamsUni.value_or(0));
auto& statelessResetToken = clientConn_->statelessResetToken; auto& statelessResetToken = clientConn_->statelessResetToken;
if (statelessResetToken) { if (statelessResetToken) {
conn_->readCodec->setStatelessResetToken(*statelessResetToken); conn_->readCodec->setStatelessResetToken(*statelessResetToken);
} }
if (zeroRttRejected.has_value() && *zeroRttRejected) { if (zeroRttRejected.has_value() && *zeroRttRejected) {
// verify that the new flow control parameters are >= the original // verify that the new flow control parameters are >= the original
// transport parameters that were use. This is the easy case. If the // transport parameters that were use. This is the easy case. If the
// flow control decreases then we are just screwed and we need to have // flow control decreases then we are just screwed and we need to have
// the app retry the connection. The other parameters can be updated. // the app retry the connection. The other parameters can be updated.
// TODO: implement undo transport state on retry. // TODO: implement undo transport state on retry.
if (originalPeerMaxOffset > if (originalPeerMaxOffset >
conn_->flowControlState.peerAdvertisedMaxOffset || conn_->flowControlState.peerAdvertisedMaxOffset ||
originalPeerInitialStreamOffsetBidiLocal > originalPeerInitialStreamOffsetBidiLocal >
conn_->flowControlState conn_->flowControlState
.peerAdvertisedInitialMaxStreamOffsetBidiLocal || .peerAdvertisedInitialMaxStreamOffsetBidiLocal ||
originalPeerInitialStreamOffsetBidiRemote > originalPeerInitialStreamOffsetBidiRemote >
conn_->flowControlState conn_->flowControlState
.peerAdvertisedInitialMaxStreamOffsetBidiRemote || .peerAdvertisedInitialMaxStreamOffsetBidiRemote ||
originalPeerInitialStreamOffsetUni > originalPeerInitialStreamOffsetUni >
conn_->flowControlState conn_->flowControlState
.peerAdvertisedInitialMaxStreamOffsetUni) { .peerAdvertisedInitialMaxStreamOffsetUni) {
throw QuicTransportException( throw QuicTransportException(
"Rejection of zero rtt parameters unsupported", "Rejection of zero rtt parameters unsupported",
TransportErrorCode::TRANSPORT_PARAMETER_ERROR); TransportErrorCode::TRANSPORT_PARAMETER_ERROR);
}
} }
} }
// TODO This sucks, but manually update the max packet size until we fix
// 0-rtt transport parameters.
if (conn_->transportSettings.canIgnorePathMTU &&
zeroRttRejected.has_value() && !*zeroRttRejected) {
auto updatedPacketSize = getIntegerParameter(
TransportParameterId::max_packet_size, serverParams->parameters);
updatedPacketSize = std::max<uint64_t>(
updatedPacketSize.value_or(kDefaultUDPSendPacketLen),
kDefaultUDPSendPacketLen);
updatedPacketSize =
std::min<uint64_t>(*updatedPacketSize, kDefaultMaxUDPPayload);
conn_->udpSendPacketLen = *updatedPacketSize;
}
} }
if (zeroRttRejected.has_value() && *zeroRttRejected) { if (zeroRttRejected.has_value() && *zeroRttRejected) {
// TODO: Make sure the alpn is the same, if not then do a full undo of the // TODO: Make sure the alpn is the same, if not then do a full undo of the
// state. // state.

View File

@@ -234,9 +234,6 @@ void updateTransportParamsFromCachedEarlyParams(
QuicClientConnectionState& conn, QuicClientConnectionState& conn,
const CachedServerTransportParameters& transportParams) { const CachedServerTransportParameters& transportParams) {
conn.peerIdleTimeout = std::chrono::milliseconds(transportParams.idleTimeout); conn.peerIdleTimeout = std::chrono::milliseconds(transportParams.idleTimeout);
if (conn.transportSettings.canIgnorePathMTU) {
conn.udpSendPacketLen = transportParams.maxRecvPacketSize;
}
conn.flowControlState.peerAdvertisedMaxOffset = conn.flowControlState.peerAdvertisedMaxOffset =
transportParams.initialMaxData; transportParams.initialMaxData;
conn.flowControlState.peerAdvertisedInitialMaxStreamOffsetBidiLocal = conn.flowControlState.peerAdvertisedInitialMaxStreamOffsetBidiLocal =

View File

@@ -61,7 +61,7 @@ TEST_F(ClientStateMachineTest, TestUpdateTransportParamsFromCachedEarlyParams) {
updateTransportParamsFromCachedEarlyParams(*client_, kParams); updateTransportParamsFromCachedEarlyParams(*client_, kParams);
EXPECT_EQ(client_->peerIdleTimeout, idleTimeout); EXPECT_EQ(client_->peerIdleTimeout, idleTimeout);
EXPECT_EQ(client_->udpSendPacketLen, maxRecvPacketSize); EXPECT_NE(client_->udpSendPacketLen, maxRecvPacketSize);
EXPECT_EQ(client_->flowControlState.peerAdvertisedMaxOffset, initialMaxData); EXPECT_EQ(client_->flowControlState.peerAdvertisedMaxOffset, initialMaxData);
EXPECT_EQ( EXPECT_EQ(
client_->flowControlState.peerAdvertisedInitialMaxStreamOffsetBidiLocal, client_->flowControlState.peerAdvertisedInitialMaxStreamOffsetBidiLocal,

View File

@@ -35,6 +35,7 @@
#include <quic/samples/echo/EchoHandler.h> #include <quic/samples/echo/EchoHandler.h>
#include <quic/samples/echo/EchoServer.h> #include <quic/samples/echo/EchoServer.h>
#include <quic/state/test/MockQuicStats.h> #include <quic/state/test/MockQuicStats.h>
#include "quic/QuicConstants.h"
using namespace testing; using namespace testing;
using namespace folly; using namespace folly;
@@ -5366,7 +5367,6 @@ TEST_F(QuicZeroRttClientTest, TestReplaySafeCallback) {
startClient(); startClient();
EXPECT_TRUE(performedValidation); EXPECT_TRUE(performedValidation);
auto initialUDPSendPacketLen = client->getConn().udpSendPacketLen;
socketWrites.clear(); socketWrites.clear();
auto streamId = client->createBidirectionalStream().value(); auto streamId = client->createBidirectionalStream().value();
client->writeChain(streamId, IOBuf::copyBuffer("hello"), true, false); client->writeChain(streamId, IOBuf::copyBuffer("hello"), true, false);
@@ -5382,12 +5382,13 @@ TEST_F(QuicZeroRttClientTest, TestReplaySafeCallback) {
// All the data is still there. // All the data is still there.
EXPECT_TRUE(zeroRttPacketsOutstanding()); EXPECT_TRUE(zeroRttPacketsOutstanding());
// Transport parameters did not change since zero rtt was accepted. // Transport parameters did not change since zero rtt was accepted.
// Except for max packet size.
verifyTransportParameters( verifyTransportParameters(
kDefaultConnectionWindowSize, kDefaultConnectionWindowSize,
kDefaultStreamWindowSize, kDefaultStreamWindowSize,
kDefaultIdleTimeout, kDefaultIdleTimeout,
kDefaultAckDelayExponent, kDefaultAckDelayExponent,
initialUDPSendPacketLen); kDefaultMaxUDPPayload);
EXPECT_CALL(*mockQuicPskCache_, putPsk(hostname_, _)) EXPECT_CALL(*mockQuicPskCache_, putPsk(hostname_, _))
.WillOnce(Invoke([=](const std::string&, QuicCachedPsk psk) { .WillOnce(Invoke([=](const std::string&, QuicCachedPsk psk) {