Add a method that writes AckFrequencyFrame in QuicControlFrameManager and code for updating peer_max_ack_delay in QuicSentPacketManager.
PiperOrigin-RevId: 332528530
Change-Id: I3a67955fc6f6f6850da117b878a189a28bf7ee4c
diff --git a/quic/core/quic_control_frame_manager.cc b/quic/core/quic_control_frame_manager.cc
index c2fdc38..28b3446 100644
--- a/quic/core/quic_control_frame_manager.cc
+++ b/quic/core/quic_control_frame_manager.cc
@@ -6,6 +6,8 @@
#include <string>
+#include "net/third_party/quiche/src/quic/core/frames/quic_ack_frequency_frame.h"
+#include "net/third_party/quiche/src/quic/core/frames/quic_frame.h"
#include "net/third_party/quiche/src/quic/core/quic_constants.h"
#include "net/third_party/quiche/src/quic/core/quic_session.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
@@ -117,6 +119,16 @@
QuicFrame(QuicHandshakeDoneFrame(++last_control_frame_id_)));
}
+void QuicControlFrameManager::WriteOrBufferAckFrequency(
+ uint64_t packet_tolerance,
+ QuicTime::Delta max_ack_delay) {
+ QUIC_DVLOG(1) << "Writing ACK_FREQUENCY frame";
+ QuicControlFrameId control_frame_id = ++last_control_frame_id_;
+ WriteOrBufferQuicFrame(QuicFrame(new QuicAckFrequencyFrame(
+ control_frame_id,
+ /*sequence_number=*/control_frame_id, packet_tolerance, max_ack_delay)));
+}
+
void QuicControlFrameManager::WritePing() {
QUIC_DVLOG(1) << "Writing PING_FRAME";
if (HasBufferedFrames()) {
diff --git a/quic/core/quic_control_frame_manager.h b/quic/core/quic_control_frame_manager.h
index d57d120..d79b679 100644
--- a/quic/core/quic_control_frame_manager.h
+++ b/quic/core/quic_control_frame_manager.h
@@ -84,6 +84,11 @@
// be sent immediately.
void WriteOrBufferHandshakeDone();
+ // Tries to send an AckFrequencyFrame. The frame is buffered if it cannot be
+ // sent immediately.
+ void WriteOrBufferAckFrequency(uint64_t packet_tolerance,
+ QuicTime::Delta max_ack_delay);
+
// Sends a PING_FRAME. Do not send PING if there is buffered frames.
void WritePing();
diff --git a/quic/core/quic_control_frame_manager_test.cc b/quic/core/quic_control_frame_manager_test.cc
index 6219038..6817699 100644
--- a/quic/core/quic_control_frame_manager_test.cc
+++ b/quic/core/quic_control_frame_manager_test.cc
@@ -6,6 +6,7 @@
#include <utility>
+#include "net/third_party/quiche/src/quic/core/frames/quic_ack_frequency_frame.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
@@ -231,6 +232,29 @@
EXPECT_FALSE(manager_->WillingToWrite());
}
+TEST_F(QuicControlFrameManagerTest, SendAndAckAckFrequencyFrame) {
+ Initialize();
+ InSequence s;
+ // Send Non-AckFrequency frame 1-5.
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .Times(5)
+ .WillRepeatedly(Invoke(&ClearControlFrame));
+ EXPECT_CALL(*connection_, SendControlFrame(_)).WillOnce(Return(false));
+ manager_->OnCanWrite();
+
+ // Send AckFrequencyFrame as frame 6.
+ QuicAckFrequencyFrame ack_frequency = {6, 6, 10,
+ QuicTime::Delta::FromMilliseconds(24)};
+ manager_->WriteOrBufferAckFrequency(10,
+ QuicTime::Delta::FromMilliseconds(24));
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .WillOnce(Invoke(&ClearControlFrame));
+ manager_->OnCanWrite();
+
+ // Ack AckFrequencyFrame.
+ EXPECT_TRUE(manager_->OnControlFrameAcked(QuicFrame(&ack_frequency)));
+}
+
TEST_F(QuicControlFrameManagerTest, DonotRetransmitOldWindowUpdates) {
Initialize();
// Send two more window updates of the same stream.
diff --git a/quic/core/quic_packet_creator.cc b/quic/core/quic_packet_creator.cc
index 939d78d..a3e2bf9 100644
--- a/quic/core/quic_packet_creator.cc
+++ b/quic/core/quic_packet_creator.cc
@@ -503,6 +503,7 @@
packet_.transmission_type = NOT_RETRANSMISSION;
packet_.encrypted_buffer = nullptr;
packet_.encrypted_length = 0;
+ packet_.has_ack_frequency = false;
packet_.fate = SEND_TO_WRITER;
QUIC_BUG_IF(packet_.release_encrypted_buffer != nullptr)
<< "packet_.release_encrypted_buffer should be empty";
@@ -1686,9 +1687,10 @@
if (frame.type == ACK_FRAME) {
packet_.has_ack = true;
packet_.largest_acked = LargestAcked(*frame.ack_frame);
- }
- if (frame.type == STOP_WAITING_FRAME) {
+ } else if (frame.type == STOP_WAITING_FRAME) {
packet_.has_stop_waiting = true;
+ } else if (frame.type == ACK_FREQUENCY_FRAME) {
+ packet_.has_ack_frequency = true;
}
if (debug_delegate_ != nullptr) {
debug_delegate_->OnFrameAddedToPacket(frame);
diff --git a/quic/core/quic_packets.cc b/quic/core/quic_packets.cc
index 30bf334..c975fe7 100644
--- a/quic/core/quic_packets.cc
+++ b/quic/core/quic_packets.cc
@@ -463,6 +463,7 @@
has_stop_waiting(has_stop_waiting),
transmission_type(NOT_RETRANSMISSION),
has_ack_frame_copy(false),
+ has_ack_frequency(false),
fate(SEND_TO_WRITER) {}
SerializedPacket::SerializedPacket(SerializedPacket&& other)
@@ -475,6 +476,7 @@
transmission_type(other.transmission_type),
largest_acked(other.largest_acked),
has_ack_frame_copy(other.has_ack_frame_copy),
+ has_ack_frequency(other.has_ack_frequency),
fate(other.fate),
peer_address(other.peer_address) {
if (this != &other) {
@@ -519,6 +521,7 @@
copy->encryption_level = serialized.encryption_level;
copy->transmission_type = serialized.transmission_type;
copy->largest_acked = serialized.largest_acked;
+ copy->has_ack_frequency = serialized.has_ack_frequency;
copy->fate = serialized.fate;
copy->peer_address = serialized.peer_address;
diff --git a/quic/core/quic_packets.h b/quic/core/quic_packets.h
index e00bcda..5941c39 100644
--- a/quic/core/quic_packets.h
+++ b/quic/core/quic_packets.h
@@ -403,6 +403,7 @@
// Indicates whether this packet has a copy of ack frame in
// nonretransmittable_frames.
bool has_ack_frame_copy;
+ bool has_ack_frequency;
SerializedPacketFate fate;
QuicSocketAddress peer_address;
};
diff --git a/quic/core/quic_sent_packet_manager.cc b/quic/core/quic_sent_packet_manager.cc
index c73fb9a..1a730e6 100644
--- a/quic/core/quic_sent_packet_manager.cc
+++ b/quic/core/quic_sent_packet_manager.cc
@@ -645,6 +645,13 @@
QuicTime ack_receive_time,
QuicTime::Delta ack_delay_time,
QuicTime receive_timestamp) {
+ if (info->has_ack_frequency) {
+ for (const auto& frame : info->retransmittable_frames) {
+ if (frame.type == ACK_FREQUENCY_FRAME) {
+ OnAckFrequencyFrameAcked(*frame.ack_frequency_frame);
+ }
+ }
+ }
// Try to aggregate acked stream frames if acked packet is not a
// retransmission.
if (info->transmission_type == NOT_RETRANSMISSION) {
@@ -722,6 +729,13 @@
one_rtt_packet_sent_ = true;
}
+ if (packet.has_ack_frequency) {
+ for (const auto& frame : packet.retransmittable_frames) {
+ if (frame.type == ACK_FREQUENCY_FRAME) {
+ OnAckFrequencyFrameSent(*frame.ack_frequency_frame);
+ }
+ }
+ }
unacked_packets_.AddSentPacket(mutable_packet, transmission_type, sent_time,
in_flight, measure_rtt);
// Reset the retransmission timer anytime a pending packet is sent.
@@ -1603,5 +1617,37 @@
: GetRetransmissionDelay();
}
+void QuicSentPacketManager::OnAckFrequencyFrameSent(
+ const QuicAckFrequencyFrame& ack_frequency_frame) {
+ in_use_sent_ack_delays_.emplace_back(ack_frequency_frame.max_ack_delay,
+ ack_frequency_frame.sequence_number);
+ if (ack_frequency_frame.max_ack_delay > peer_max_ack_delay_) {
+ peer_max_ack_delay_ = ack_frequency_frame.max_ack_delay;
+ }
+}
+
+void QuicSentPacketManager::OnAckFrequencyFrameAcked(
+ const QuicAckFrequencyFrame& ack_frequency_frame) {
+ int stale_entry_count = 0;
+ for (auto it = in_use_sent_ack_delays_.cbegin();
+ it != in_use_sent_ack_delays_.cend(); ++it) {
+ if (it->second < ack_frequency_frame.sequence_number) {
+ ++stale_entry_count;
+ } else {
+ break;
+ }
+ }
+ if (stale_entry_count > 0) {
+ in_use_sent_ack_delays_.pop_front_n(stale_entry_count);
+ }
+ if (in_use_sent_ack_delays_.empty()) {
+ QUIC_BUG << "in_use_sent_ack_delays_ is empty.";
+ return;
+ }
+ peer_max_ack_delay_ = std::max_element(in_use_sent_ack_delays_.cbegin(),
+ in_use_sent_ack_delays_.cend())
+ ->first;
+}
+
#undef ENDPOINT // undef for jumbo builds
} // namespace quic
diff --git a/quic/core/quic_sent_packet_manager.h b/quic/core/quic_sent_packet_manager.h
index 6719a94..3420140 100644
--- a/quic/core/quic_sent_packet_manager.h
+++ b/quic/core/quic_sent_packet_manager.h
@@ -6,6 +6,7 @@
#define QUICHE_QUIC_CORE_QUIC_SENT_PACKET_MANAGER_H_
#include <cstddef>
+#include <cstdint>
#include <map>
#include <memory>
#include <set>
@@ -18,6 +19,7 @@
#include "net/third_party/quiche/src/quic/core/congestion_control/send_algorithm_interface.h"
#include "net/third_party/quiche/src/quic/core/congestion_control/uber_loss_algorithm.h"
#include "net/third_party/quiche/src/quic/core/proto/cached_network_parameters_proto.h"
+#include "net/third_party/quiche/src/quic/core/quic_circular_deque.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/core/quic_sustained_bandwidth_recorder.h"
#include "net/third_party/quiche/src/quic/core/quic_transmission_info.h"
@@ -554,6 +556,14 @@
// retransmission timer is not armed if there is no packets in flight.
bool PeerCompletedAddressValidation() const;
+ // Called when an AckFrequencyFrame is sent.
+ void OnAckFrequencyFrameSent(
+ const QuicAckFrequencyFrame& ack_frequency_frame);
+
+ // Called when an AckFrequencyFrame is acked.
+ void OnAckFrequencyFrameAcked(
+ const QuicAckFrequencyFrame& ack_frequency_frame);
+
// Newly serialized retransmittable packets are added to this map, which
// contains owning pointers to any contained frames. If a packet is
// retransmitted, this map will contain entries for both the old and the new
@@ -633,11 +643,17 @@
QuicPacketNumber
largest_packets_peer_knows_is_acked_[NUM_PACKET_NUMBER_SPACES];
- // The maximum ACK delay time that the peer uses. Initialized to be the
+ // The maximum ACK delay time that the peer might uses. Initialized to be the
// same as local_max_ack_delay_, may be changed via transport parameter
- // negotiation.
+ // negotiation or subsequently by AckFrequencyFrame.
QuicTime::Delta peer_max_ack_delay_;
+ // The history of outstanding max_ack_delays sent to peer. Outstanding means
+ // a max_ack_delay is sent as part of the last acked AckFrequencyFrame or
+ // an unacked AckFrequencyFrame after that.
+ QuicCircularDeque<std::pair<QuicTime::Delta, /*sequence_number=*/uint64_t>>
+ in_use_sent_ack_delays_;
+
// Latest received ack frame.
QuicAckFrame last_ack_frame_;
diff --git a/quic/core/quic_sent_packet_manager_test.cc b/quic/core/quic_sent_packet_manager_test.cc
index c5fb920..05da9df 100644
--- a/quic/core/quic_sent_packet_manager_test.cc
+++ b/quic/core/quic_sent_packet_manager_test.cc
@@ -7,6 +7,8 @@
#include <memory>
#include <utility>
+#include "net/third_party/quiche/src/quic/core/frames/quic_ack_frequency_frame.h"
+#include "net/third_party/quiche/src/quic/core/quic_time.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
@@ -4230,6 +4232,184 @@
ENCRYPTION_FORWARD_SECURE));
}
+SerializedPacket MakePacketWithAckFrequencyFrame(
+ int packet_number,
+ int ack_frequency_sequence_number,
+ QuicTime::Delta max_ack_delay) {
+ auto* ack_frequency_frame = new QuicAckFrequencyFrame();
+ ack_frequency_frame->max_ack_delay = max_ack_delay;
+ ack_frequency_frame->sequence_number = ack_frequency_sequence_number;
+ SerializedPacket packet(QuicPacketNumber(packet_number),
+ PACKET_4BYTE_PACKET_NUMBER, nullptr, kDefaultLength,
+ /*has_ack=*/false,
+ /*has_stop_waiting=*/false);
+ packet.retransmittable_frames.push_back(QuicFrame(ack_frequency_frame));
+ packet.has_ack_frequency = true;
+ packet.encryption_level = ENCRYPTION_FORWARD_SECURE;
+ return packet;
+}
+
+TEST_F(QuicSentPacketManagerTest,
+ PeerMaxAckDelayUpdatedFromAckFrequencyFrameOneAtATime) {
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AnyNumber());
+ EXPECT_CALL(*send_algorithm_, OnCongestionEvent(_, _, _, _, _))
+ .Times(AnyNumber());
+ EXPECT_CALL(*network_change_visitor_, OnCongestionChange())
+ .Times(AnyNumber());
+
+ auto initial_peer_max_ack_delay = manager_.peer_max_ack_delay();
+ auto one_ms = QuicTime::Delta::FromMilliseconds(1);
+ auto plus_1_ms_delay = initial_peer_max_ack_delay + one_ms;
+ auto minus_1_ms_delay = initial_peer_max_ack_delay - one_ms;
+
+ // Send and Ack frame1.
+ SerializedPacket packet1 = MakePacketWithAckFrequencyFrame(
+ /*packet_number=*/1, /*ack_frequency_sequence_number=*/1,
+ plus_1_ms_delay);
+ // Higher on the fly max_ack_delay changes peer_max_ack_delay.
+ manager_.OnPacketSent(&packet1, clock_.Now(), NOT_RETRANSMISSION,
+ HAS_RETRANSMITTABLE_DATA, /*measure_rtt=*/true);
+ EXPECT_EQ(manager_.peer_max_ack_delay(), plus_1_ms_delay);
+ manager_.OnAckFrameStart(QuicPacketNumber(1), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2));
+ manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(1),
+ ENCRYPTION_FORWARD_SECURE);
+ EXPECT_EQ(manager_.peer_max_ack_delay(), plus_1_ms_delay);
+
+ // Send and Ack frame2.
+ SerializedPacket packet2 = MakePacketWithAckFrequencyFrame(
+ /*packet_number=*/2, /*ack_frequency_sequence_number=*/2,
+ minus_1_ms_delay);
+ // Lower on the fly max_ack_delay does not change peer_max_ack_delay.
+ manager_.OnPacketSent(&packet2, clock_.Now(), NOT_RETRANSMISSION,
+ HAS_RETRANSMITTABLE_DATA, /*measure_rtt=*/true);
+ EXPECT_EQ(manager_.peer_max_ack_delay(), plus_1_ms_delay);
+ manager_.OnAckFrameStart(QuicPacketNumber(2), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(2), QuicPacketNumber(3));
+ manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(2),
+ ENCRYPTION_FORWARD_SECURE);
+ EXPECT_EQ(manager_.peer_max_ack_delay(), minus_1_ms_delay);
+}
+
+TEST_F(QuicSentPacketManagerTest,
+ PeerMaxAckDelayUpdatedFromInOrderAckFrequencyFrames) {
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AnyNumber());
+ EXPECT_CALL(*send_algorithm_, OnCongestionEvent(_, _, _, _, _))
+ .Times(AnyNumber());
+ EXPECT_CALL(*network_change_visitor_, OnCongestionChange())
+ .Times(AnyNumber());
+
+ auto initial_peer_max_ack_delay = manager_.peer_max_ack_delay();
+ auto one_ms = QuicTime::Delta::FromMilliseconds(1);
+ auto extra_1_ms = initial_peer_max_ack_delay + one_ms;
+ auto extra_2_ms = initial_peer_max_ack_delay + 2 * one_ms;
+ auto extra_3_ms = initial_peer_max_ack_delay + 3 * one_ms;
+ SerializedPacket packet1 = MakePacketWithAckFrequencyFrame(
+ /*packet_number=*/1, /*ack_frequency_sequence_number=*/1, extra_1_ms);
+ SerializedPacket packet2 = MakePacketWithAckFrequencyFrame(
+ /*packet_number=*/2, /*ack_frequency_sequence_number=*/2, extra_3_ms);
+ SerializedPacket packet3 = MakePacketWithAckFrequencyFrame(
+ /*packet_number=*/3, /*ack_frequency_sequence_number=*/3, extra_2_ms);
+
+ // Send frame1, farme2, frame3.
+ manager_.OnPacketSent(&packet1, clock_.Now(), NOT_RETRANSMISSION,
+ HAS_RETRANSMITTABLE_DATA, /*measure_rtt=*/true);
+ EXPECT_EQ(manager_.peer_max_ack_delay(), extra_1_ms);
+ manager_.OnPacketSent(&packet2, clock_.Now(), NOT_RETRANSMISSION,
+ HAS_RETRANSMITTABLE_DATA, /*measure_rtt=*/true);
+ EXPECT_EQ(manager_.peer_max_ack_delay(), extra_3_ms);
+ manager_.OnPacketSent(&packet3, clock_.Now(), NOT_RETRANSMISSION,
+ HAS_RETRANSMITTABLE_DATA, /*measure_rtt=*/true);
+ EXPECT_EQ(manager_.peer_max_ack_delay(), extra_3_ms);
+
+ // Ack frame1, farme2, frame3.
+ manager_.OnAckFrameStart(QuicPacketNumber(1), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2));
+ manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(1),
+ ENCRYPTION_FORWARD_SECURE);
+ EXPECT_EQ(manager_.peer_max_ack_delay(), extra_3_ms);
+ manager_.OnAckFrameStart(QuicPacketNumber(2), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(3));
+ manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(1),
+ ENCRYPTION_FORWARD_SECURE);
+ EXPECT_EQ(manager_.peer_max_ack_delay(), extra_3_ms);
+ manager_.OnAckFrameStart(QuicPacketNumber(3), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(4));
+ manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(1),
+ ENCRYPTION_FORWARD_SECURE);
+ EXPECT_EQ(manager_.peer_max_ack_delay(), extra_2_ms);
+}
+
+TEST_F(QuicSentPacketManagerTest,
+ PeerMaxAckDelayUpdatedFromOutOfOrderAckedAckFrequencyFrames) {
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AnyNumber());
+ EXPECT_CALL(*send_algorithm_, OnCongestionEvent(_, _, _, _, _))
+ .Times(AnyNumber());
+ EXPECT_CALL(*network_change_visitor_, OnCongestionChange())
+ .Times(AnyNumber());
+
+ auto initial_peer_max_ack_delay = manager_.peer_max_ack_delay();
+ auto one_ms = QuicTime::Delta::FromMilliseconds(1);
+ auto extra_1_ms = initial_peer_max_ack_delay + one_ms;
+ auto extra_2_ms = initial_peer_max_ack_delay + 2 * one_ms;
+ auto extra_3_ms = initial_peer_max_ack_delay + 3 * one_ms;
+ auto extra_4_ms = initial_peer_max_ack_delay + 4 * one_ms;
+ SerializedPacket packet1 = MakePacketWithAckFrequencyFrame(
+ /*packet_number=*/1, /*ack_frequency_sequence_number=*/1, extra_4_ms);
+ SerializedPacket packet2 = MakePacketWithAckFrequencyFrame(
+ /*packet_number=*/2, /*ack_frequency_sequence_number=*/2, extra_3_ms);
+ SerializedPacket packet3 = MakePacketWithAckFrequencyFrame(
+ /*packet_number=*/3, /*ack_frequency_sequence_number=*/3, extra_2_ms);
+ SerializedPacket packet4 = MakePacketWithAckFrequencyFrame(
+ /*packet_number=*/4, /*ack_frequency_sequence_number=*/4, extra_1_ms);
+
+ // Send frame1, farme2, frame3, frame4.
+ manager_.OnPacketSent(&packet1, clock_.Now(), NOT_RETRANSMISSION,
+ HAS_RETRANSMITTABLE_DATA, /*measure_rtt=*/true);
+ manager_.OnPacketSent(&packet2, clock_.Now(), NOT_RETRANSMISSION,
+ HAS_RETRANSMITTABLE_DATA, /*measure_rtt=*/true);
+ manager_.OnPacketSent(&packet3, clock_.Now(), NOT_RETRANSMISSION,
+ HAS_RETRANSMITTABLE_DATA, /*measure_rtt=*/true);
+ manager_.OnPacketSent(&packet4, clock_.Now(), NOT_RETRANSMISSION,
+ NO_RETRANSMITTABLE_DATA, /*measure_rtt=*/true);
+ EXPECT_EQ(manager_.peer_max_ack_delay(), extra_4_ms);
+
+ // Ack frame3.
+ manager_.OnAckFrameStart(QuicPacketNumber(3), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(3), QuicPacketNumber(4));
+ manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(1),
+ ENCRYPTION_FORWARD_SECURE);
+ EXPECT_EQ(manager_.peer_max_ack_delay(), extra_2_ms);
+ // Acking frame1 do not affect peer_max_ack_delay after frame3 is acked.
+ manager_.OnAckFrameStart(QuicPacketNumber(3), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(3), QuicPacketNumber(4));
+ manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2));
+ manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(1),
+ ENCRYPTION_FORWARD_SECURE);
+ EXPECT_EQ(manager_.peer_max_ack_delay(), extra_2_ms);
+ // Acking frame2 do not affect peer_max_ack_delay after frame3 is acked.
+ manager_.OnAckFrameStart(QuicPacketNumber(3), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(4));
+ manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(1),
+ ENCRYPTION_FORWARD_SECURE);
+ EXPECT_EQ(manager_.peer_max_ack_delay(), extra_2_ms);
+ // Acking frame4 updates peer_max_ack_delay.
+ manager_.OnAckFrameStart(QuicPacketNumber(4), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(5));
+ manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(1),
+ ENCRYPTION_FORWARD_SECURE);
+ EXPECT_EQ(manager_.peer_max_ack_delay(), extra_1_ms);
+}
+
} // namespace
} // namespace test
} // namespace quic
diff --git a/quic/core/quic_transmission_info.cc b/quic/core/quic_transmission_info.cc
index a27b769..02b34b5 100644
--- a/quic/core/quic_transmission_info.cc
+++ b/quic/core/quic_transmission_info.cc
@@ -13,20 +13,23 @@
transmission_type(NOT_RETRANSMISSION),
in_flight(false),
state(OUTSTANDING),
- has_crypto_handshake(false) {}
+ has_crypto_handshake(false),
+ has_ack_frequency(false) {}
QuicTransmissionInfo::QuicTransmissionInfo(EncryptionLevel level,
TransmissionType transmission_type,
QuicTime sent_time,
QuicPacketLength bytes_sent,
- bool has_crypto_handshake)
+ bool has_crypto_handshake,
+ bool has_ack_frequency)
: encryption_level(level),
bytes_sent(bytes_sent),
sent_time(sent_time),
transmission_type(transmission_type),
in_flight(false),
state(OUTSTANDING),
- has_crypto_handshake(has_crypto_handshake) {}
+ has_crypto_handshake(has_crypto_handshake),
+ has_ack_frequency(has_ack_frequency) {}
QuicTransmissionInfo::QuicTransmissionInfo(const QuicTransmissionInfo& other) =
default;
diff --git a/quic/core/quic_transmission_info.h b/quic/core/quic_transmission_info.h
index 6023665..acc5667 100644
--- a/quic/core/quic_transmission_info.h
+++ b/quic/core/quic_transmission_info.h
@@ -25,7 +25,8 @@
TransmissionType transmission_type,
QuicTime sent_time,
QuicPacketLength bytes_sent,
- bool has_crypto_handshake);
+ bool has_crypto_handshake,
+ bool has_ack_frequency);
QuicTransmissionInfo(const QuicTransmissionInfo& other);
@@ -43,6 +44,8 @@
SentPacketState state;
// True if the packet contains stream data from the crypto stream.
bool has_crypto_handshake;
+ // True if the packet contains ack frequency frame.
+ bool has_ack_frequency;
// Records the first sent packet after this packet was detected lost. Zero if
// this packet has not been detected lost. This is used to keep lost packet
// for another RTT (for potential spurious loss detection)
diff --git a/quic/core/quic_unacked_packet_map.cc b/quic/core/quic_unacked_packet_map.cc
index 3d5579d..3e377cf 100644
--- a/quic/core/quic_unacked_packet_map.cc
+++ b/quic/core/quic_unacked_packet_map.cc
@@ -148,7 +148,8 @@
const bool has_crypto_handshake = packet.has_crypto_handshake == IS_HANDSHAKE;
QuicTransmissionInfo info(packet.encryption_level, transmission_type,
- sent_time, bytes_sent, has_crypto_handshake);
+ sent_time, bytes_sent, has_crypto_handshake,
+ packet.has_ack_frequency);
info.largest_acked = packet.largest_acked;
largest_sent_largest_acked_.UpdateMax(packet.largest_acked);