quic/state/TransportSettings.h (122 lines of code) (raw):
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
#include <quic/QuicConstants.h>
#include <quic/codec/QuicConnectionId.h>
#include <quic/d6d/Types.h>
#include <chrono>
namespace quic {
struct BbrConfig {
bool conservativeRecovery{false};
/**
* When largeProbeRttCwnd is true, kLargeProbeRttCwndGain * BDP will be used
* as cwnd during ProbeRtt state, otherwise, 4MSS will be the ProbeRtt cwnd.
*/
bool largeProbeRttCwnd{false};
// Whether ack aggregation is also calculated during Startup phase
bool enableAckAggregationInStartup{false};
/**
* Whether we should enter ProbeRtt if connection has been app-limited since
* last time we ProbeRtt.
*/
bool probeRttDisabledIfAppLimited{false};
/**
* Whether BBR should advance pacing gain cycle when BBR is draining and we
* haven't reached the drain target.
*/
bool drainToTarget{false};
};
struct CcpConfig {
std::string alg_name = "";
std::string alg_args = "";
};
struct D6DConfig {
/**
* Currently, only server does probing, so this flags means different things
* for server and client. For server, it means whether it should enable d6d
* when it receives the base PMTU transport parameter. For client, it means
* whether it will send the base PMTU transport parameter during handshake.
* As a result, d6d is activated for a connection only when *both* client and
* server enables d6d.
*
* TODO: Please make sure QuicConnectionStateBase::D6DState::outstandingProbes
* are mutated correctly throughout Mvfst.
*/
bool enabled{false};
/**
* Base PMTU that client advertises to server. This is needed because
* depending on the situation there are clients who want to start from a
* larger/smaller base PMTU. Server makes no use of this value, but should
* rely on the transport parameter received from client.
*/
uint16_t advertisedBasePMTU{kDefaultD6DBasePMTU};
/**
* The number of "big" packet losses we can tolerate before signalling PMTU
* blackhole.
*/
uint64_t blackholeDetectionThreshold{kDefaultD6DBlackholeDetectionThreshold};
/**
* The constant pmtu step size used for ConstantStep probe size raiser
*/
uint16_t probeRaiserConstantStepSize{kDefaultD6DProbeStepSize};
/**
* The D6D raise timeout that client advertises to server. We might need to
* tune this value for different paths. Again, server makes no use of this
* value, but should rely on the transport parameter.
*/
std::chrono::seconds advertisedRaiseTimeout{kDefaultD6DRaiseTimeout};
/**
* The D6D probe timeout. When it expires, we either send another
* probe with the same size, or sleep for raise timeout, depending
* on the d6d state. There are other events (e.g. probe gets acked
* or probe is determined lost) that might cancel this timeout.
* Client sends this value as a transport parameter during
* handshake.
*/
std::chrono::seconds advertisedProbeTimeout{kDefaultD6DProbeTimeout};
/**
* The moving window within which we check if the detection threshold has been
* crossed
*/
std::chrono::seconds blackholeDetectionWindow{
kDefaultD6DBlackholeDetectionWindow};
/**
* Default raiser is constant step , since overshot caused by binary
* search slows down convergence. Might change in the future when we
* have more context.
*/
ProbeSizeRaiserType raiserType{ProbeSizeRaiserType::ConstantStep};
};
struct DatagramConfig {
bool enabled{false};
bool framePerPacket{true};
bool recvDropOldDataFirst{false};
bool sendDropOldDataFirst{false};
uint32_t readBufSize{kDefaultMaxDatagramsBuffered};
uint32_t writeBufSize{kDefaultMaxDatagramsBuffered};
};
// JSON-serialized transport knobs
struct SerializedKnob {
uint64_t space;
uint64_t id;
std::string blob;
};
struct TransportSettings {
// The initial connection window advertised to the peer.
uint64_t advertisedInitialConnectionWindowSize{kDefaultConnectionWindowSize};
// The initial window size of the stream advertised to the peer.
uint64_t advertisedInitialBidiLocalStreamWindowSize{kDefaultStreamWindowSize};
uint64_t advertisedInitialBidiRemoteStreamWindowSize{
kDefaultStreamWindowSize};
uint64_t advertisedInitialUniStreamWindowSize{kDefaultStreamWindowSize};
uint64_t advertisedInitialMaxStreamsBidi{kDefaultMaxStreamsBidirectional};
uint64_t advertisedInitialMaxStreamsUni{kDefaultMaxStreamsUnidirectional};
// Maximum number of packets to buffer while cipher is unavailable.
uint32_t maxPacketsToBuffer{kDefaultMaxBufferedPackets};
// Idle timeout to advertise to the peer.
std::chrono::milliseconds idleTimeout{kDefaultIdleTimeout};
// Ack delay exponent to use.
uint64_t ackDelayExponent{kDefaultAckDelayExponent};
// Default congestion controller type.
CongestionControlType defaultCongestionController{
CongestionControlType::Cubic};
// Param to determine sensitivity of CongestionController to latency. Only
// used by Copa.
folly::Optional<double> copaDeltaParam;
// Whether to use Copa's RTT standing feature. Only used by Copa.
bool copaUseRttStanding{false};
// The max UDP packet size we are willing to receive.
uint64_t maxRecvPacketSize{kDefaultUDPReadBufferSize};
// Number of buffers to allocate for GRO
uint32_t numGROBuffers_{kDefaultNumGROBuffers};
// Can we ignore the path mtu when sending a packet. This is useful for
// testing.
bool canIgnorePathMTU{false};
// Whether or not to use a connected UDP socket on the client. This should
// only be used in environments where you know your IP address does not
// change. See AsyncUDPSocket::connect for the caveats.
bool connectUDP{false};
// Maximum number of consecutive PTOs before the connection is torn down.
uint16_t maxNumPTOs{kDefaultMaxNumPTO};
// Whether to listen to socket error
bool enableSocketErrMsgCallback{true};
// Whether pacing is enabled.
bool pacingEnabled{false};
// The minimum number of packets to burst out during pacing
uint64_t minBurstPackets{kDefaultMinBurstPackets};
// Pacing timer tick interval
std::chrono::microseconds pacingTimerTickInterval{
kDefaultPacingTimerTickInterval};
ZeroRttSourceTokenMatchingPolicy zeroRttSourceTokenMatchingPolicy{
ZeroRttSourceTokenMatchingPolicy::REJECT_IF_NO_EXACT_MATCH};
// Scale pacing rate for CC, non-empty indicates override via transport knobs
std::pair<uint8_t, uint8_t> startupRttFactor{1, 2};
std::pair<uint8_t, uint8_t> defaultRttFactor{4, 5};
//
bool attemptEarlyData{false};
// Maximum number of packets the connection will write in
// writeConnectionDataToSocket.
uint64_t writeConnectionDataPacketsLimit{
kDefaultWriteConnectionDataPacketLimit};
// Fraction of RTT that is used to limit how long a write function can loop
DurationRep writeLimitRttFraction{kDefaultWriteLimitRttFraction};
// Frequency of sending flow control updates. We can send one update every
// flowControlRttFrequency * RTT if the flow control changes.
uint16_t flowControlRttFrequency{2};
// Frequency of sending flow control updates. We can send one update every
// flowControlWindowFrequency * window if the flow control changes.
uint16_t flowControlWindowFrequency{2};
// batching mode
QuicBatchingMode batchingMode{QuicBatchingMode::BATCHING_MODE_NONE};
// use thread local batcher - currently it works only with
// BATCHING_MODE_SENDMMSG_GSO it will not be enabled if the mode is different
bool useThreadLocalBatching{false};
// thread local delay interval
std::chrono::microseconds threadLocalDelay{kDefaultThreadLocalDelay};
// maximum number of packets we can batch. This does not apply to
// BATCHING_MODE_NONE
uint32_t maxBatchSize{kDefaultQuicMaxBatchSize};
// Initial congestion window in MSS
uint64_t initCwndInMss{kInitCwndInMss};
// Minimum congestion window in MSS
uint64_t minCwndInMss{kMinCwndInMss};
// Maximum congestion window in MSS
uint64_t maxCwndInMss{kDefaultMaxCwndInMss};
// Limited congestion window in MSS
uint64_t limitedCwndInMss{kLimitedCwndInMss};
// The following three parameters control ACK generation. ACKs are sent every
// time so many retransmittable packets are received. There are two values,
// one for earlier in the flow and one for after. These are "before" and
// "after" the init threshold respectively.
uint64_t rxPacketsBeforeAckInitThreshold{
kDefaultRxPacketsBeforeAckInitThreshold};
uint16_t rxPacketsBeforeAckBeforeInit{kDefaultRxPacketsBeforeAckBeforeInit};
uint16_t rxPacketsBeforeAckAfterInit{kDefaultRxPacketsBeforeAckAfterInit};
folly::Optional<std::chrono::microseconds> minAckDelay;
// Limits the amount of data that should be buffered in a QuicSocket.
// If the amount of data in the buffer equals or exceeds this amount, then
// the callback registered through notifyPendingWriteOnConnection() will
// not be called
uint64_t totalBufferSpaceAvailable{kDefaultBufferSpaceAvailable};
// Whether the endpoint allows peer to migrate to new address
bool disableMigration{true};
// Whether or not the socket should gracefully drain on close
bool shouldDrain{true};
// default stateless reset secret for stateless reset token
folly::Optional<std::array<uint8_t, kStatelessResetTokenSecretLength>>
statelessResetTokenSecret;
// retry token secret used for encryption/decryption
folly::Optional<std::array<uint8_t, kRetryTokenSecretLength>>
retryTokenSecret;
// Default initial RTT
std::chrono::microseconds initialRtt{kDefaultInitialRtt};
// The active_connection_id_limit that is sent to the peer.
uint64_t selfActiveConnectionIdLimit{kDefaultActiveConnectionIdLimit};
// Maximum size of the batch that should be used when receiving packets from
// the kernel in one event loop.
size_t maxRecvBatchSize{5};
// Whether or not we should recv data in a batch.
bool shouldRecvBatch{false};
// Whether or not use recvmmsg when shouldRecvBatch is true.
bool shouldUseRecvmmsgForBatchRecv{false};
// Config struct for BBR
BbrConfig bbrConfig;
// Config struct for CCP
CcpConfig ccpConfig;
// A packet is considered loss when a packet that's sent later by at least
// timeReorderingThreshold * RTT is acked by peer.
DurationRep timeReorderingThreshDividend{
kDefaultTimeReorderingThreshDividend};
DurationRep timeReorderingThreshDivisor{kDefaultTimeReorderingThreshDivisor};
// A temporary type to control DataPath write style. Will be gone after we
// are done with experiment.
DataPathType dataPathType{DataPathType::ChainedMemory};
// Whether or not we should stop writing a packet after writing a single
// stream frame to it.
bool streamFramePerPacket{false};
// Ensure read callbacks are ordered by Stream ID.
bool orderedReadCallbacks{false};
// Config struct for D6D
D6DConfig d6dConfig;
// Quic knobs
std::vector<SerializedKnob> knobs;
// Datagram config
DatagramConfig datagramConfig;
// Whether or not to opportunistically retransmit 0RTT when the handshake
// completes.
bool earlyRetransmit0Rtt{false};
// Whether to use JumpStarter as the CongestionControllerFactory
bool useJumpStart{false};
// Whether to issue new tokens via NewToken frames.
bool issueNewTokens{false};
// Used to generate the number of frames to add to short header packets.
// Packets will have padding frames added such that the total space remaining
// in a packet is always an increment of paddingModulo, hiding the actual
// packet size from packet analysis.
// Padding Modulo of 0 turns off padding for short header packets.
size_t paddingModulo{kShortHeaderPaddingModulo};
// Whether to use adaptive loss thresholds for reodering and timeout
bool useAdaptiveLossThresholds{false};
// Whether to automatically increase receive conn flow control. The
// determination is based on the frequency we are sending flow control
// updates. If there has been less than 2SRTTs between flow control updates
// this will double the target window.
bool autotuneReceiveConnFlowControl{false};
// Enable a keepalive timer. This schedules a timer to send a PING ~15%
// before an idle timeout. To work effectively this means the idle timer
// has to be set to something >> the RTT of the connection.
bool enableKeepalive{false};
std::string flowPriming = "";
};
} // namespace quic