Parse and frame the updated ACK_FREQUENCY frame and implement the logic for receiving it.

In a change from draft-iyengar-quic-delayed-ack-01, previously missing packets are always acknowledged regardless of reordering_threshold.

Protected by FLAGS_quic_reloadable_flag_quic_receive_ack_frequency.

PiperOrigin-RevId: 765276193
diff --git a/quiche/quic/core/frames/quic_ack_frequency_frame.cc b/quiche/quic/core/frames/quic_ack_frequency_frame.cc
index 7faf7f1..bcb6888 100644
--- a/quiche/quic/core/frames/quic_ack_frequency_frame.cc
+++ b/quiche/quic/core/frames/quic_ack_frequency_frame.cc
@@ -5,25 +5,27 @@
 #include "quiche/quic/core/frames/quic_ack_frequency_frame.h"
 
 #include <cstdint>
-#include <limits>
 #include <ostream>
 
 namespace quic {
 
 QuicAckFrequencyFrame::QuicAckFrequencyFrame(
     QuicControlFrameId control_frame_id, uint64_t sequence_number,
-    uint64_t packet_tolerance, QuicTime::Delta max_ack_delay)
+    uint64_t ack_eliciting_threshold, QuicTime::Delta requested_max_ack_delay,
+    uint64_t reordering_threshold)
     : control_frame_id(control_frame_id),
       sequence_number(sequence_number),
-      packet_tolerance(packet_tolerance),
-      max_ack_delay(max_ack_delay) {}
+      ack_eliciting_threshold(ack_eliciting_threshold),
+      requested_max_ack_delay(requested_max_ack_delay),
+      reordering_threshold(reordering_threshold) {}
 
 std::ostream& operator<<(std::ostream& os, const QuicAckFrequencyFrame& frame) {
   os << "{ control_frame_id: " << frame.control_frame_id
      << ", sequence_number: " << frame.sequence_number
-     << ", packet_tolerance: " << frame.packet_tolerance
-     << ", max_ack_delay_ms: " << frame.max_ack_delay.ToMilliseconds()
-     << ", ignore_order: " << frame.ignore_order << " }\n";
+     << ", ack_eliciting_threshold: " << frame.ack_eliciting_threshold
+     << ", requested_max_ack_delay_ms: "
+     << frame.requested_max_ack_delay.ToMilliseconds()
+     << ", reordering_threshold: " << frame.reordering_threshold << " }\n";
   return os;
 }
 
diff --git a/quiche/quic/core/frames/quic_ack_frequency_frame.h b/quiche/quic/core/frames/quic_ack_frequency_frame.h
index 660b1a7..22fe058 100644
--- a/quiche/quic/core/frames/quic_ack_frequency_frame.h
+++ b/quiche/quic/core/frames/quic_ack_frequency_frame.h
@@ -11,7 +11,7 @@
 #include "quiche/quic/core/quic_constants.h"
 #include "quiche/quic/core/quic_time.h"
 #include "quiche/quic/core/quic_types.h"
-#include "quiche/quic/platform/api/quic_export.h"
+#include "quiche/common/platform/api/quiche_export.h"
 
 namespace quic {
 
@@ -21,28 +21,32 @@
       std::ostream& os, const QuicAckFrequencyFrame& ack_frequency_frame);
 
   QuicAckFrequencyFrame() = default;
+  // Set a default for reordering_threshold so it does not break Envoy tests.
   QuicAckFrequencyFrame(QuicControlFrameId control_frame_id,
-                        uint64_t sequence_number, uint64_t packet_tolerance,
-                        QuicTime::Delta max_ack_delay);
+                        uint64_t sequence_number,
+                        uint64_t ack_eliciting_threshold,
+                        QuicTime::Delta requested_max_ack_delay,
+                        uint64_t reordering_threshold = 1);
 
   // A unique identifier of this control frame. 0 when this frame is
   // received, and non-zero when sent.
   QuicControlFrameId control_frame_id = kInvalidControlFrameId;
 
-  // If true, do not ack immediately upon observeation of packet reordering.
-  bool ignore_order = false;
-
   // Sequence number assigned to the ACK_FREQUENCY frame by the sender to allow
   // receivers to ignore obsolete frames.
   uint64_t sequence_number = 0;
 
-  // The maximum number of ack-eliciting packets after which the receiver sends
-  // an acknowledgement. Invald if == 0.
-  uint64_t packet_tolerance = 2;
+  // The maximum number of ack-eliciting packets that do not require an
+  // acknowledgement.
+  uint64_t ack_eliciting_threshold = 1;
 
   // The maximum time that ack packets can be delayed.
-  QuicTime::Delta max_ack_delay =
+  QuicTime::Delta requested_max_ack_delay =
       QuicTime::Delta::FromMilliseconds(kDefaultPeerDelayedAckTimeMs);
+
+  // The number of out-of-order packets necessary to trigger an immediate
+  // acknowledgement. If zero, OOO packets are not acked immediately.
+  uint64_t reordering_threshold = 1;
 };
 
 }  // namespace quic
diff --git a/quiche/quic/core/frames/quic_frames_test.cc b/quiche/quic/core/frames/quic_frames_test.cc
index e6a843d..eeed473 100644
--- a/quiche/quic/core/frames/quic_frames_test.cc
+++ b/quiche/quic/core/frames/quic_frames_test.cc
@@ -327,12 +327,13 @@
   EXPECT_TRUE(IsControlFrame(frame.type));
 }
 
-TEST_F(QuicFramesTest, QuicAckFreuqncyFrameToString) {
+TEST_F(QuicFramesTest, QuicAckFrequencyFrameToString) {
   QuicAckFrequencyFrame ack_frequency_frame;
   ack_frequency_frame.sequence_number = 1;
-  ack_frequency_frame.packet_tolerance = 2;
-  ack_frequency_frame.max_ack_delay = QuicTime::Delta::FromMilliseconds(25);
-  ack_frequency_frame.ignore_order = false;
+  ack_frequency_frame.ack_eliciting_threshold = 2;
+  ack_frequency_frame.requested_max_ack_delay =
+      QuicTime::Delta::FromMilliseconds(25);
+  ack_frequency_frame.reordering_threshold = false;
   QuicFrame frame(&ack_frequency_frame);
   ASSERT_EQ(ACK_FREQUENCY_FRAME, frame.type);
   SetControlFrameId(6, &frame);
@@ -340,8 +341,8 @@
   std::ostringstream stream;
   stream << *frame.ack_frequency_frame;
   EXPECT_EQ(
-      "{ control_frame_id: 6, sequence_number: 1, packet_tolerance: 2, "
-      "max_ack_delay_ms: 25, ignore_order: 0 }\n",
+      "{ control_frame_id: 6, sequence_number: 1, ack_eliciting_threshold: 2, "
+      "requested_max_ack_delay_ms: 25, reordering_threshold: 0 }\n",
       stream.str());
   EXPECT_TRUE(IsControlFrame(frame.type));
 }
diff --git a/quiche/quic/core/quic_connection.cc b/quiche/quic/core/quic_connection.cc
index 214414a..74ac6e4 100644
--- a/quiche/quic/core/quic_connection.cc
+++ b/quiche/quic/core/quic_connection.cc
@@ -607,6 +607,8 @@
     if (config.GetMinAckDelayDraft10ToSendMs() <=
         config.GetMaxAckDelayToSendMs()) {  // MinAckDelay is valid.
       set_can_receive_ack_frequency_immediate_ack(true);
+      local_min_ack_delay_ = QuicTime::Delta::FromMilliseconds(
+          config.GetMinAckDelayDraft10ToSendMs());
     } else {
       QUIC_BUG(quic_bug_min_ack_delay_too_high)
           << "MinAckDelay higher than MaxAckDelay";
@@ -2116,6 +2118,15 @@
     QUIC_LOG_EVERY_N_SEC(ERROR, 120) << "Get unexpected AckFrequencyFrame.";
     return false;
   }
+  if (frame.requested_max_ack_delay < local_min_ack_delay_) {
+    QUIC_LOG_EVERY_N_SEC(ERROR, 120)
+        << "Received AckFrequencyFrame with requested_max_ack_delay "
+        << frame.requested_max_ack_delay
+        << " which is less than the minimum ack delay " << local_min_ack_delay_;
+    CloseConnection(IETF_QUIC_PROTOCOL_VIOLATION, "MaxAckDelay too small",
+                    ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+    return false;
+  }
   if (auto packet_number_space =
           QuicUtils::GetPacketNumberSpace(
               last_received_packet_info_.decrypted_level) == APPLICATION_DATA) {
@@ -4087,10 +4098,11 @@
     QUIC_RELOADABLE_FLAG_COUNT_N(quic_can_send_ack_frequency, 2, 3);
     auto ack_frequency_frame =
         sent_packet_manager_.GetUpdatedAckFrequencyFrame();
-    // This AckFrequencyFrame is meant to only update the max_ack_delay. Set
-    // packet tolerance to the default value for now.
-    ack_frequency_frame.packet_tolerance =
+    // This AckFrequencyFrame is meant to only update the max_ack_delay. All
+    // other values are set to the default.
+    ack_frequency_frame.ack_eliciting_threshold =
         kDefaultRetransmittablePacketsBeforeAck;
+    ack_frequency_frame.reordering_threshold = 1;
     visitor_->SendAckFrequency(ack_frequency_frame);
     if (!connected_) {
       return;
diff --git a/quiche/quic/core/quic_connection.h b/quiche/quic/core/quic_connection.h
index a2f7bfa..e2073c5 100644
--- a/quiche/quic/core/quic_connection.h
+++ b/quiche/quic/core/quic_connection.h
@@ -2530,6 +2530,9 @@
 
   QuicTime::Delta multi_port_probing_interval_;
 
+  // The minimum ack delay time advertised to the peer via transport parameter.
+  QuicTime::Delta local_min_ack_delay_ = QuicTime::Delta::Zero();
+
   std::unique_ptr<MultiPortStats> multi_port_stats_;
 
   // If true, connection will migrate to multi-port path upon path degrading.
diff --git a/quiche/quic/core/quic_connection_test.cc b/quiche/quic/core/quic_connection_test.cc
index 1950e10..915f65d 100644
--- a/quiche/quic/core/quic_connection_test.cc
+++ b/quiche/quic/core/quic_connection_test.cc
@@ -4,8 +4,6 @@
 
 #include "quiche/quic/core/quic_connection.h"
 
-#include <errno.h>
-
 #include <algorithm>
 #include <cstdint>
 #include <memory>
@@ -3592,7 +3590,7 @@
   EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
 
   QuicAckFrequencyFrame ack_frequency_frame;
-  ack_frequency_frame.packet_tolerance = 3;
+  ack_frequency_frame.ack_eliciting_threshold = 2;
   ProcessFramePacketAtLevel(1, QuicFrame(&ack_frequency_frame),
                             ENCRYPTION_FORWARD_SECURE);
 
@@ -13299,8 +13297,8 @@
   // Send packet 101.
   SendStreamDataToPeer(/*id=*/1, "bar", /*offset=*/3, NO_FIN, nullptr);
 
-  EXPECT_EQ(captured_frame.packet_tolerance, 10u);
-  EXPECT_EQ(captured_frame.max_ack_delay,
+  EXPECT_EQ(captured_frame.ack_eliciting_threshold, 10u);
+  EXPECT_EQ(captured_frame.requested_max_ack_delay,
             QuicTime::Delta::FromMilliseconds(GetDefaultDelayedAckTimeMs()));
 
   // Sending packet 102 does not trigger sending another AckFrequencyFrame.
@@ -13339,8 +13337,8 @@
 
   connection_.OnHandshakeComplete();
 
-  EXPECT_EQ(captured_frame.packet_tolerance, 2u);
-  EXPECT_EQ(captured_frame.max_ack_delay,
+  EXPECT_EQ(captured_frame.ack_eliciting_threshold, 2u);
+  EXPECT_EQ(captured_frame.requested_max_ack_delay,
             QuicTime::Delta::FromMilliseconds(GetDefaultDelayedAckTimeMs()));
 }
 
diff --git a/quiche/quic/core/quic_control_frame_manager.cc b/quiche/quic/core/quic_control_frame_manager.cc
index 9dd73a1..b5dbbba 100644
--- a/quiche/quic/core/quic_control_frame_manager.cc
+++ b/quiche/quic/core/quic_control_frame_manager.cc
@@ -137,11 +137,12 @@
   QuicControlFrameId control_frame_id = ++last_control_frame_id_;
   // Using the control_frame_id for sequence_number here leaves gaps in
   // sequence_number.
-  WriteOrBufferQuicFrame(
-      QuicFrame(new QuicAckFrequencyFrame(control_frame_id,
-                                          /*sequence_number=*/control_frame_id,
-                                          ack_frequency_frame.packet_tolerance,
-                                          ack_frequency_frame.max_ack_delay)));
+  WriteOrBufferQuicFrame(QuicFrame(
+      new QuicAckFrequencyFrame(control_frame_id,
+                                /*sequence_number=*/control_frame_id,
+                                ack_frequency_frame.ack_eliciting_threshold,
+                                ack_frequency_frame.requested_max_ack_delay,
+                                ack_frequency_frame.reordering_threshold)));
 }
 
 void QuicControlFrameManager::WriteOrBufferNewConnectionId(
diff --git a/quiche/quic/core/quic_control_frame_manager_test.cc b/quiche/quic/core/quic_control_frame_manager_test.cc
index a007d92..d58ffed 100644
--- a/quiche/quic/core/quic_control_frame_manager_test.cc
+++ b/quiche/quic/core/quic_control_frame_manager_test.cc
@@ -421,8 +421,9 @@
 TEST_F(QuicControlFrameManagerTest, SendAndAckAckFrequencyFrame) {
   // Send AckFrequencyFrame
   QuicAckFrequencyFrame frame_to_send;
-  frame_to_send.packet_tolerance = 10;
-  frame_to_send.max_ack_delay = QuicTime::Delta::FromMilliseconds(24);
+  frame_to_send.ack_eliciting_threshold = 10;
+  frame_to_send.requested_max_ack_delay = QuicTime::Delta::FromMilliseconds(24);
+  frame_to_send.reordering_threshold = 3;
   EXPECT_CALL(*session_, WriteControlFrame(_, _))
       .WillOnce(Invoke(&ClearControlFrameWithTransmissionType));
   manager_->WriteOrBufferAckFrequency(frame_to_send);
diff --git a/quiche/quic/core/quic_framer.cc b/quiche/quic/core/quic_framer.cc
index a506624..e01b1af 100644
--- a/quiche/quic/core/quic_framer.cc
+++ b/quiche/quic/core/quic_framer.cc
@@ -628,10 +628,10 @@
     const QuicAckFrequencyFrame& frame) {
   return QuicDataWriter::GetVarInt62Len(IETF_ACK_FREQUENCY) +
          QuicDataWriter::GetVarInt62Len(frame.sequence_number) +
-         QuicDataWriter::GetVarInt62Len(frame.packet_tolerance) +
-         QuicDataWriter::GetVarInt62Len(frame.max_ack_delay.ToMicroseconds()) +
-         // One byte for encoding boolean
-         1;
+         QuicDataWriter::GetVarInt62Len(frame.ack_eliciting_threshold) +
+         QuicDataWriter::GetVarInt62Len(
+             frame.requested_max_ack_delay.ToMicroseconds()) +
+         QuicDataWriter::GetVarInt62Len(frame.reordering_threshold);
 }
 
 // static
@@ -3391,14 +3391,10 @@
     return false;
   }
 
-  if (!reader->ReadVarInt62(&frame->packet_tolerance)) {
+  if (!reader->ReadVarInt62(&frame->ack_eliciting_threshold)) {
     set_detailed_error("Unable to read packet tolerance.");
     return false;
   }
-  if (frame->packet_tolerance == 0) {
-    set_detailed_error("Invalid packet tolerance.");
-    return false;
-  }
   uint64_t max_ack_delay_us;
   if (!reader->ReadVarInt62(&max_ack_delay_us)) {
     set_detailed_error("Unable to read max_ack_delay_us.");
@@ -3409,19 +3405,13 @@
     set_detailed_error("Invalid max_ack_delay_us.");
     return false;
   }
-  frame->max_ack_delay = QuicTime::Delta::FromMicroseconds(max_ack_delay_us);
+  frame->requested_max_ack_delay =
+      QuicTime::Delta::FromMicroseconds(max_ack_delay_us);
 
-  uint8_t ignore_order;
-  if (!reader->ReadUInt8(&ignore_order)) {
-    set_detailed_error("Unable to read ignore_order.");
+  if (!reader->ReadVarInt62(&frame->reordering_threshold)) {
+    set_detailed_error("Unable to read reordering_threshold.");
     return false;
   }
-  if (ignore_order > 1) {
-    set_detailed_error("Invalid ignore_order.");
-    return false;
-  }
-  frame->ignore_order = ignore_order;
-
   return true;
 }
 
@@ -5270,17 +5260,17 @@
     set_detailed_error("Writing sequence number failed.");
     return false;
   }
-  if (!writer->WriteVarInt62(frame.packet_tolerance)) {
+  if (!writer->WriteVarInt62(frame.ack_eliciting_threshold)) {
     set_detailed_error("Writing packet tolerance failed.");
     return false;
   }
-  if (!writer->WriteVarInt62(
-          static_cast<uint64_t>(frame.max_ack_delay.ToMicroseconds()))) {
+  if (!writer->WriteVarInt62(static_cast<uint64_t>(
+          frame.requested_max_ack_delay.ToMicroseconds()))) {
     set_detailed_error("Writing max_ack_delay_us failed.");
     return false;
   }
-  if (!writer->WriteUInt8(static_cast<uint8_t>(frame.ignore_order))) {
-    set_detailed_error("Writing ignore_order failed.");
+  if (!writer->WriteVarInt62(frame.reordering_threshold)) {
+    set_detailed_error("Writing reordering_threshold failed.");
     return false;
   }
 
diff --git a/quiche/quic/core/quic_framer_test.cc b/quiche/quic/core/quic_framer_test.cc
index cced010..c8a79b3 100644
--- a/quiche/quic/core/quic_framer_test.cc
+++ b/quiche/quic/core/quic_framer_test.cc
@@ -4847,12 +4847,12 @@
      0x40, 0xAF,
      // sequence_number
      0x11,
-     // packet_tolerance
+     // ack_eliciting_threshold
      0x02,
      // max_ack_delay_us = 2'5000 us
      0x80, 0x00, 0x61, 0xA8,
-     // ignore_order
-     0x01
+     // reordering_threshold = 0 (ignore order)
+     0x00
   };
   // clang-format on
 
@@ -4872,9 +4872,9 @@
   ASSERT_EQ(1u, visitor_.ack_frequency_frames_.size());
   const auto& frame = visitor_.ack_frequency_frames_.front();
   EXPECT_EQ(17u, frame->sequence_number);
-  EXPECT_EQ(2u, frame->packet_tolerance);
-  EXPECT_EQ(2'5000u, frame->max_ack_delay.ToMicroseconds());
-  EXPECT_EQ(true, frame->ignore_order);
+  EXPECT_EQ(2u, frame->ack_eliciting_threshold);
+  EXPECT_EQ(2'5000u, frame->requested_max_ack_delay.ToMicroseconds());
+  EXPECT_EQ(0u, frame->reordering_threshold);
 }
 
 TEST_P(QuicFramerTest, ParseImmediateAckFrame) {
@@ -8253,9 +8253,10 @@
 
   QuicAckFrequencyFrame ack_frequency_frame;
   ack_frequency_frame.sequence_number = 3;
-  ack_frequency_frame.packet_tolerance = 5;
-  ack_frequency_frame.max_ack_delay = QuicTime::Delta::FromMicroseconds(0x3fff);
-  ack_frequency_frame.ignore_order = false;
+  ack_frequency_frame.ack_eliciting_threshold = 5;
+  ack_frequency_frame.requested_max_ack_delay =
+      QuicTime::Delta::FromMicroseconds(0x3fff);
+  ack_frequency_frame.reordering_threshold = 3;
   QuicFrames frames = {QuicFrame(&ack_frequency_frame)};
 
   // clang-format off
@@ -8271,12 +8272,12 @@
     0x40, 0xaf,
     // sequence number
     0x03,
-    // packet tolerance
+    // ack-eliciting threshold
     0x05,
     // max_ack_delay_us
     0x7f, 0xff,
-    // ignore_oder
-    0x00
+    // reordering threshold
+    0x03
   };
   // clang-format on
   if (!VersionHasIetfQuicFrames(framer_.transport_version())) {
diff --git a/quiche/quic/core/quic_received_packet_manager.cc b/quiche/quic/core/quic_received_packet_manager.cc
index 72a1425..5e18cab 100644
--- a/quiche/quic/core/quic_received_packet_manager.cc
+++ b/quiche/quic/core/quic_received_packet_manager.cc
@@ -12,6 +12,7 @@
 #include "quiche/quic/core/crypto/crypto_protocol.h"
 #include "quiche/quic/core/quic_config.h"
 #include "quiche/quic/core/quic_connection_stats.h"
+#include "quiche/quic/core/quic_time.h"
 #include "quiche/quic/core/quic_types.h"
 #include "quiche/quic/platform/api/quic_bug_tracker.h"
 #include "quiche/quic/platform/api/quic_flag_utils.h"
@@ -45,17 +46,14 @@
       stats_(stats),
       num_retransmittable_packets_received_since_last_ack_sent_(0),
       min_received_before_ack_decimation_(kMinReceivedBeforeAckDecimation),
-      ack_frequency_(kDefaultRetransmittablePacketsBeforeAck),
       ack_decimation_delay_(GetQuicFlag(quic_ack_decimation_delay)),
       unlimited_ack_decimation_(false),
       one_immediate_ack_(false),
-      ignore_order_(false),
       local_max_ack_delay_(
           QuicTime::Delta::FromMilliseconds(GetDefaultDelayedAckTimeMs())),
       ack_timeout_(QuicTime::Zero()),
       time_of_previous_received_packet_(QuicTime::Zero()),
-      was_last_packet_missing_(false),
-      last_ack_frequency_frame_sequence_number_(-1) {}
+      was_last_packet_missing_(false) {}
 
 QuicReceivedPacketManager::~QuicReceivedPacketManager() {}
 
@@ -294,11 +292,12 @@
     return;
   }
 
-  if (!ignore_order_ && was_last_packet_missing_ &&
-      last_sent_largest_acked_.IsInitialized() &&
+  // TODO(martinduke): If a missing packet is received, do we send it when
+  // reordering_threshold_ == 0?
+  if (was_last_packet_missing_ && last_sent_largest_acked_.IsInitialized() &&
       last_received_packet_number < last_sent_largest_acked_) {
-    // Only ack immediately if an ACK frame was sent with a larger largest acked
-    // than the newly received packet number.
+    // Ack immediately if an ACK frame was sent with a larger largest acked than
+    // the newly received packet number.
     ack_timeout_ = now;
     return;
   }
@@ -322,7 +321,7 @@
     return;
   }
 
-  if (!ignore_order_ && HasNewMissingPackets()) {
+  if (reordering_threshold_ == 1 && HasNewMissingPackets()) {  // Fast path.
     ack_timeout_ = now;
     return;
   }
@@ -384,15 +383,14 @@
 
 void QuicReceivedPacketManager::OnAckFrequencyFrame(
     const QuicAckFrequencyFrame& frame) {
-  int64_t new_sequence_number = frame.sequence_number;
-  if (new_sequence_number <= last_ack_frequency_frame_sequence_number_) {
+  if (frame.sequence_number < next_ack_frequency_frame_sequence_number_) {
     // Ignore old ACK_FREQUENCY frames.
     return;
   }
-  last_ack_frequency_frame_sequence_number_ = new_sequence_number;
-  ack_frequency_ = frame.packet_tolerance;
-  local_max_ack_delay_ = frame.max_ack_delay;
-  ignore_order_ = frame.ignore_order;
+  next_ack_frequency_frame_sequence_number_ = frame.sequence_number + 1;
+  ack_frequency_ = frame.ack_eliciting_threshold + 1;
+  local_max_ack_delay_ = frame.requested_max_ack_delay;
+  reordering_threshold_ = frame.reordering_threshold;
 }
 
 }  // namespace quic
diff --git a/quiche/quic/core/quic_received_packet_manager.h b/quiche/quic/core/quic_received_packet_manager.h
index d1feccc..404d46d 100644
--- a/quiche/quic/core/quic_received_packet_manager.h
+++ b/quiche/quic/core/quic_received_packet_manager.h
@@ -6,13 +6,15 @@
 #define QUICHE_QUIC_CORE_QUIC_RECEIVED_PACKET_MANAGER_H_
 
 #include <cstddef>
+#include <cstdint>
 
 #include "quiche/quic/core/frames/quic_ack_frequency_frame.h"
 #include "quiche/quic/core/quic_config.h"
-#include "quiche/quic/core/quic_framer.h"
+#include "quiche/quic/core/quic_constants.h"
 #include "quiche/quic/core/quic_packets.h"
+#include "quiche/quic/core/quic_time.h"
 #include "quiche/quic/core/quic_types.h"
-#include "quiche/quic/platform/api/quic_export.h"
+#include "quiche/common/platform/api/quiche_export.h"
 
 namespace quic {
 
@@ -146,7 +148,7 @@
                                  const RttStats& rtt_stats) const;
 
   bool AckFrequencyFrameReceived() const {
-    return last_ack_frequency_frame_sequence_number_ >= 0;
+    return next_ack_frequency_frame_sequence_number_ > 0;
   }
 
   void MaybeTrimAckRanges();
@@ -186,8 +188,8 @@
   QuicPacketCount num_retransmittable_packets_received_since_last_ack_sent_;
   // Ack decimation will start happening after this many packets are received.
   size_t min_received_before_ack_decimation_;
-  // Ack every n-th packet.
-  size_t ack_frequency_;
+  // Ack every nth packet.
+  size_t ack_frequency_ = kDefaultRetransmittablePacketsBeforeAck;
   // The max delay in fraction of min_rtt to use when sending decimated acks.
   float ack_decimation_delay_;
   // When true, removes ack decimation's max number of packets(10) before
@@ -195,12 +197,16 @@
   bool unlimited_ack_decimation_;
   // When true, only send 1 immediate ACK when reordering is detected.
   bool one_immediate_ack_;
-  // When true, do not ack immediately upon observation of packet reordering.
-  bool ignore_order_;
+  // If the largest unacked packet has a packet number that is
+  // reordering_threshold_ more than the lowest missing packet number that is
+  // greater than largest_acked, then an immediate ACK will be sent. The default
+  // value is 1. A value of 0 means to ignore reordering.
+  uint64_t reordering_threshold_ = 1;
 
   // The local node's maximum ack delay time. This is the maximum amount of
   // time to wait before sending an acknowledgement.
   QuicTime::Delta local_max_ack_delay_;
+
   // Time that an ACK needs to be sent. 0 means no ACK is pending. Used when
   // decide_when_to_send_acks_ is true.
   QuicTime ack_timeout_;
@@ -222,9 +228,8 @@
   // Last sent largest acked, which gets updated when ACK was successfully sent.
   QuicPacketNumber last_sent_largest_acked_;
 
-  // The sequence number of the last received AckFrequencyFrame. Negative if
-  // none received.
-  int64_t last_ack_frequency_frame_sequence_number_;
+  // The expected sequence number of the next received AckFrequencyFrame.
+  uint64_t next_ack_frequency_frame_sequence_number_ = 0;
 };
 
 }  // namespace quic
diff --git a/quiche/quic/core/quic_received_packet_manager_test.cc b/quiche/quic/core/quic_received_packet_manager_test.cc
index 1f4aaee..97f00c5 100644
--- a/quiche/quic/core/quic_received_packet_manager_test.cc
+++ b/quiche/quic/core/quic_received_packet_manager_test.cc
@@ -543,17 +543,17 @@
   EXPECT_FALSE(HasPendingAck());
 
   QuicAckFrequencyFrame frame;
-  frame.max_ack_delay = QuicTime::Delta::FromMilliseconds(10);
-  frame.packet_tolerance = 5;
+  frame.requested_max_ack_delay = QuicTime::Delta::FromMilliseconds(10);
+  frame.ack_eliciting_threshold = 4;
   received_manager_.OnAckFrequencyFrame(frame);
 
   for (int i = 1; i <= 50; ++i) {
     RecordPacketReceipt(i, clock_.ApproximateNow());
     MaybeUpdateAckTimeout(kInstigateAck, i);
-    if (i % frame.packet_tolerance == 0) {
+    if (i % (frame.ack_eliciting_threshold + 1) == 0) {
       CheckAckTimeout(clock_.ApproximateNow());
     } else {
-      CheckAckTimeout(clock_.ApproximateNow() + frame.max_ack_delay);
+      CheckAckTimeout(clock_.ApproximateNow() + frame.requested_max_ack_delay);
     }
   }
 }
@@ -563,9 +563,9 @@
   EXPECT_FALSE(HasPendingAck());
 
   QuicAckFrequencyFrame frame;
-  frame.max_ack_delay = kDelayedAckTime;
-  frame.packet_tolerance = 2;
-  frame.ignore_order = true;
+  frame.requested_max_ack_delay = kDelayedAckTime;
+  frame.ack_eliciting_threshold = 1;
+  frame.reordering_threshold = 0;
   received_manager_.OnAckFrequencyFrame(frame);
 
   RecordPacketReceipt(4, clock_.ApproximateNow());
@@ -578,27 +578,27 @@
 
   RecordPacketReceipt(3, clock_.ApproximateNow());
   MaybeUpdateAckTimeout(kInstigateAck, 3);
-  // Don't ack as ignore_order is set by AckFrequencyFrame.
-  CheckAckTimeout(clock_.ApproximateNow() + kDelayedAckTime);
-
-  RecordPacketReceipt(2, clock_.ApproximateNow());
-  MaybeUpdateAckTimeout(kInstigateAck, 2);
-  // Immediate ack is sent as this is the 2nd packet of every two packets.
+  // Ack, since missing packets are always acknowledged.
   CheckAckTimeout(clock_.ApproximateNow());
 
-  RecordPacketReceipt(1, clock_.ApproximateNow());
-  MaybeUpdateAckTimeout(kInstigateAck, 1);
-  // Don't ack as ignore_order is set by AckFrequencyFrame.
+  RecordPacketReceipt(7, clock_.ApproximateNow());
+  MaybeUpdateAckTimeout(kInstigateAck, 10);
+  // No ack, as the frame says to ignore ordering.
   CheckAckTimeout(clock_.ApproximateNow() + kDelayedAckTime);
+
+  RecordPacketReceipt(1, clock_.ApproximateNow());
+  MaybeUpdateAckTimeout(kInstigateAck, 11);
+  // It's the second packet in a row, ack it.
+  CheckAckTimeout(clock_.ApproximateNow());
 }
 
 TEST_F(QuicReceivedPacketManagerTest,
-       DisableMissingPaketsAckByIgnoreOrderFromAckFrequencyFrame) {
+       DisableMissingPacketsAckByIgnoreOrderFromAckFrequencyFrame) {
   EXPECT_FALSE(HasPendingAck());
   QuicAckFrequencyFrame frame;
-  frame.max_ack_delay = kDelayedAckTime;
-  frame.packet_tolerance = 2;
-  frame.ignore_order = true;
+  frame.requested_max_ack_delay = kDelayedAckTime;
+  frame.ack_eliciting_threshold = 1;
+  frame.reordering_threshold = 0;
   received_manager_.OnAckFrequencyFrame(frame);
 
   RecordPacketReceipt(1, clock_.ApproximateNow());
@@ -622,8 +622,7 @@
 
   RecordPacketReceipt(7, clock_.ApproximateNow());
   MaybeUpdateAckTimeout(kInstigateAck, 7);
-  // Don't ack even if packet 6 is newly missing as ignore_order is set by
-  // AckFrequencyFrame.
+  // Don't ack as AckFrequencyFrame says to ignore ordering.
   CheckAckTimeout(clock_.ApproximateNow() + kDelayedAckTime);
 }
 
@@ -632,9 +631,9 @@
   EXPECT_FALSE(HasPendingAck());
 
   QuicAckFrequencyFrame frame;
-  frame.max_ack_delay = kDelayedAckTime;
-  frame.packet_tolerance = 3;
-  frame.ignore_order = true;
+  frame.requested_max_ack_delay = kDelayedAckTime;
+  frame.ack_eliciting_threshold = 2;
+  frame.reordering_threshold = 0;
   received_manager_.OnAckFrequencyFrame(frame);
 
   // Process all the packets in order so there aren't missing packets.
diff --git a/quiche/quic/core/quic_sent_packet_manager.cc b/quiche/quic/core/quic_sent_packet_manager.cc
index 2e10bbc..ac1cc36 100644
--- a/quiche/quic/core/quic_sent_packet_manager.cc
+++ b/quiche/quic/core/quic_sent_packet_manager.cc
@@ -637,6 +637,7 @@
   return !peer_min_ack_delay_.IsInfinite() && handshake_finished_;
 }
 
+// TODO(martinduke): Update to include reordering threshold.
 QuicAckFrequencyFrame QuicSentPacketManager::GetUpdatedAckFrequencyFrame()
     const {
   QuicAckFrequencyFrame frame;
@@ -647,15 +648,16 @@
   }
 
   QUIC_RELOADABLE_FLAG_COUNT_N(quic_can_send_ack_frequency, 1, 3);
-  frame.packet_tolerance = kMaxRetransmittablePacketsBeforeAck;
+  frame.ack_eliciting_threshold = kMaxRetransmittablePacketsBeforeAck;
   auto rtt = use_smoothed_rtt_in_ack_delay_ ? rtt_stats_.SmoothedOrInitialRtt()
                                             : rtt_stats_.MinOrInitialRtt();
-  frame.max_ack_delay = rtt * kPeerAckDecimationDelay;
-  frame.max_ack_delay = std::max(frame.max_ack_delay, peer_min_ack_delay_);
+  frame.requested_max_ack_delay = rtt * kPeerAckDecimationDelay;
+  frame.requested_max_ack_delay =
+      std::max(frame.requested_max_ack_delay, peer_min_ack_delay_);
   // TODO(haoyuewang) Remove this once kDefaultMinAckDelayTimeMs is updated to
   // 5 ms on the client side.
-  frame.max_ack_delay =
-      std::max(frame.max_ack_delay,
+  frame.requested_max_ack_delay =
+      std::max(frame.requested_max_ack_delay,
                QuicTime::Delta::FromMilliseconds(kDefaultMinAckDelayTimeMs));
   return frame;
 }
@@ -1611,10 +1613,11 @@
 
 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;
+  in_use_sent_ack_delays_.emplace_back(
+      ack_frequency_frame.requested_max_ack_delay,
+      ack_frequency_frame.sequence_number);
+  if (ack_frequency_frame.requested_max_ack_delay > peer_max_ack_delay_) {
+    peer_max_ack_delay_ = ack_frequency_frame.requested_max_ack_delay;
   }
 }
 
diff --git a/quiche/quic/core/quic_sent_packet_manager_test.cc b/quiche/quic/core/quic_sent_packet_manager_test.cc
index 5e92c19..f325d58 100644
--- a/quiche/quic/core/quic_sent_packet_manager_test.cc
+++ b/quiche/quic/core/quic_sent_packet_manager_test.cc
@@ -2845,7 +2845,7 @@
     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->requested_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,
@@ -3074,10 +3074,10 @@
       /*now=*/QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(24));
 
   auto frame = manager_.GetUpdatedAckFrequencyFrame();
-  EXPECT_EQ(frame.max_ack_delay,
+  EXPECT_EQ(frame.requested_max_ack_delay,
             std::max(rtt_stats->min_rtt() * 0.25,
                      QuicTime::Delta::FromMilliseconds(1u)));
-  EXPECT_EQ(frame.packet_tolerance, 10u);
+  EXPECT_EQ(frame.ack_eliciting_threshold, 10u);
 }
 
 TEST_F(QuicSentPacketManagerTest, SmoothedRttIgnoreAckDelay) {
@@ -3216,7 +3216,7 @@
       /*now=*/QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(24));
 
   auto frame = manager_.GetUpdatedAckFrequencyFrame();
-  EXPECT_EQ(frame.max_ack_delay,
+  EXPECT_EQ(frame.requested_max_ack_delay,
             std::max(rtt_stats->SmoothedOrInitialRtt() * 0.25,
                      QuicTime::Delta::FromMilliseconds(1u)));
 }
diff --git a/quiche/quic/test_tools/simple_session_notifier.cc b/quiche/quic/test_tools/simple_session_notifier.cc
index d72b431..6e06b8c 100644
--- a/quiche/quic/test_tools/simple_session_notifier.cc
+++ b/quiche/quic/test_tools/simple_session_notifier.cc
@@ -4,13 +4,13 @@
 
 #include "quiche/quic/test_tools/simple_session_notifier.h"
 
+#include "quiche/quic/core/frames/quic_ack_frequency_frame.h"
 #include "quiche/quic/core/frames/quic_frame.h"
 #include "quiche/quic/core/frames/quic_reset_stream_at_frame.h"
 #include "quiche/quic/core/quic_error_codes.h"
 #include "quiche/quic/core/quic_types.h"
 #include "quiche/quic/core/quic_utils.h"
 #include "quiche/quic/platform/api/quic_logging.h"
-#include "quiche/quic/test_tools/quic_test_utils.h"
 
 namespace quic {
 
@@ -170,11 +170,12 @@
   const bool had_buffered_data =
       HasBufferedStreamData() || HasBufferedControlFrames();
   QuicControlFrameId control_frame_id = ++last_control_frame_id_;
-  control_frames_.emplace_back((
-      QuicFrame(new QuicAckFrequencyFrame(control_frame_id,
-                                          /*sequence_number=*/control_frame_id,
-                                          ack_frequency_frame.packet_tolerance,
-                                          ack_frequency_frame.max_ack_delay))));
+  control_frames_.emplace_back((QuicFrame(
+      new QuicAckFrequencyFrame(control_frame_id,
+                                /*sequence_number=*/control_frame_id,
+                                ack_frequency_frame.ack_eliciting_threshold,
+                                ack_frequency_frame.requested_max_ack_delay,
+                                ack_frequency_frame.reordering_threshold))));
   if (had_buffered_data) {
     QUIC_DLOG(WARNING) << "Connection is write blocked";
     return;
diff --git a/quiche/quic/test_tools/simple_session_notifier.h b/quiche/quic/test_tools/simple_session_notifier.h
index dc3bcb2..eec1b6a 100644
--- a/quiche/quic/test_tools/simple_session_notifier.h
+++ b/quiche/quic/test_tools/simple_session_notifier.h
@@ -6,11 +6,11 @@
 #define QUICHE_QUIC_TEST_TOOLS_SIMPLE_SESSION_NOTIFIER_H_
 
 #include "absl/container/flat_hash_map.h"
+#include "quiche/quic/core/quic_connection.h"
 #include "quiche/quic/core/quic_error_codes.h"
 #include "quiche/quic/core/quic_interval_set.h"
 #include "quiche/quic/core/quic_types.h"
 #include "quiche/quic/core/session_notifier_interface.h"
-#include "quiche/quic/platform/api/quic_test.h"
 #include "quiche/common/quiche_circular_deque.h"
 #include "quiche/common/quiche_linked_hash_map.h"