1
0
mirror of https://github.com/facebookincubator/mvfst.git synced 2025-11-24 04:01:07 +03:00

Write ACK_EXTENDED frame when supported by peer

Summary:
Write the new ACK_EXTENDED frame. When any of the ACK_EXTENDED features are enabled locally and supported by the peer, this frame type will take precedence over ACK_ECN and ACK_RECEIVETIMESTAMPS. See first diff in the stack for the features.

Frame format:
```
ACK_EXTENDED Frame {
  Type (i) = 0xB1
  // Fields of the existing ACK (type=0x02) frame:
  Largest Acknowledged (i),
  ACK Delay (i),
  ACK Range Count (i),
  First ACK Range (i),
  ACK Range (..) ...,
  Extended Ack Features (i),
  // Optional ECN counts (if bit 0 is set in Features)
  [ECN Counts (..)],
  // Optional Receive Timestamps (if bit 1 is set in Features)
  [Receive Timestamps (..)]
}
// Fields from the existing ACK_ECN frame
ECN Counts {
  ECT0 Count (i),
  ECT1 Count (i),
  ECN-CE Count (i),
}
// Fields from the existing ACK_RECEIVE_TIMESTAMPS frame
Receive Timestamps {
  Timestamp Range Count (i),
  Timestamp Ranges (..) ...,
}
Timestamp Range {
  Gap (i),
  Timestamp Delta Count (i),
  Timestamp Delta (i) ...,
}
```

Reviewed By: sharmafb

Differential Revision: D68931148

fbshipit-source-id: 0fb4bac23e121f82a11602daabc1ec7084db43dd
This commit is contained in:
Joseph Beshay
2025-02-24 12:32:50 -08:00
committed by Facebook GitHub Bot
parent 31fbb343d1
commit aac108ddc7
8 changed files with 400 additions and 70 deletions

View File

@@ -569,15 +569,36 @@ Optional<WriteAckFrameResult> writeAckFrame(
PacketBuilderInterface& builder,
FrameType frameType,
const AckReceiveTimestampsConfig& recvTimestampsConfig,
uint64_t maxRecvTimestampsToSend) {
uint64_t maxRecvTimestampsToSend,
ExtendedAckFeatureMaskType extendedAckFeatures) {
if (ackFrameMetaData.ackState.acks.empty()) {
return none;
}
uint64_t beginningSpace = builder.remainingSpaceInPkt();
uint64_t spaceLeft = beginningSpace;
bool ecnEnabled = (frameType == FrameType::ACK_ECN) ||
(extendedAckFeatures &
static_cast<ExtendedAckFeatureMaskType>(
ExtendedAckFeatureMask::ECN_COUNTS));
bool receiveTimestampsEnabled =
(frameType == FrameType::ACK_RECEIVE_TIMESTAMPS) ||
(extendedAckFeatures &
static_cast<ExtendedAckFeatureMaskType>(
ExtendedAckFeatureMask::RECEIVE_TIMESTAMPS));
// Reserve space for ACK_EXTENDED header
if (frameType == FrameType::ACK_EXTENDED) {
auto extendedAckRequiredSpace = QuicInteger(extendedAckFeatures).getSize();
if (spaceLeft < extendedAckRequiredSpace) {
return none;
}
spaceLeft -= extendedAckRequiredSpace;
}
// Reserve space for ECN counts if enabled
if (frameType == FrameType::ACK_ECN) {
if (ecnEnabled) {
auto ecnRequiredSpace = computeEcnRequiredSpace(ackFrameMetaData);
if (spaceLeft < ecnRequiredSpace) {
return none;
@@ -586,7 +607,7 @@ Optional<WriteAckFrameResult> writeAckFrame(
}
// Reserve space for receive timestamps if enabled
if (frameType == FrameType::ACK_RECEIVE_TIMESTAMPS) {
if (receiveTimestampsEnabled) {
auto receiveTimestampsMinimumSpace =
computeReceiveTimestampsMinimumSpace(ackFrameMetaData);
if (spaceLeft < receiveTimestampsMinimumSpace) {
@@ -597,7 +618,7 @@ Optional<WriteAckFrameResult> writeAckFrame(
// Start writing fields to the builder
// 1. Write the base ack fields (ACK packet type)
// 1. Write the base ack fields
auto maybeAckFrame =
maybeWriteAckBaseFields(ackFrameMetaData, builder, frameType, spaceLeft);
if (!maybeAckFrame.has_value()) {
@@ -605,14 +626,20 @@ Optional<WriteAckFrameResult> writeAckFrame(
}
auto& ackFrame = maybeAckFrame.value();
// 2. Write ECN fields if enabled
if (frameType == FrameType::ACK_ECN) {
// 2. Write extended ack header if enabled
if (frameType == FrameType::ACK_EXTENDED) {
QuicInteger quicExtendedAckFeatures(extendedAckFeatures);
builder.write(quicExtendedAckFeatures);
}
// 3. Write ECN fields if enabled
if (ecnEnabled) {
writeECNFieldsToAck(ackFrameMetaData, ackFrame, builder);
}
// 3. Write receive timestamp fields if enabled
// 4. Write receive timestamp fields if enabled
AckReceiveTimesStampsWritten receiveTimestampsWritten;
if (frameType == FrameType::ACK_RECEIVE_TIMESTAMPS) {
if (receiveTimestampsEnabled) {
receiveTimestampsWritten = writeReceiveTimestampFieldsToAck(
ackFrameMetaData,
ackFrame,
@@ -626,7 +653,8 @@ Optional<WriteAckFrameResult> writeAckFrame(
ackFrame,
ackFrame.ackBlocks.size(),
receiveTimestampsWritten.TimestampRangesWritten,
receiveTimestampsWritten.TimestampWritten);
receiveTimestampsWritten.TimestampWritten,
extendedAckFeatures);
builder.appendFrame(std::move(ackFrame));
return ackFrameWriteResult;