Receive ECN marks on inbound packets and report counts in ACK_ECN frames.
It does not support marking outbound packets except for a minimal capability for test.
QuicPacketReader receives ECN marks from the socket API via QuicUdpPacketInfo.. QuicPacketReader then stores this in a new member of QuicReceivedPacket. This arrives at QuicConnection, which adds to the last_received_packet_info_. When the framer calls QuicConnection::OnPacketHeader(), QuicConnection updates the pending ack frame with the new ECN count via QuicReceivedPacketManager, which updates the counts in the ack frame.
To enable an end-to-end test, this CL also includes minimal changes to mark outbound packets and report the contents of ACK_ECN frames.
QuicConnection::per_packet_options_ is extended to include an ECN codepoint, which QuicDefaultPacketWriter reads, and passes the instruction to the QuicUdpSocketApi via QuicUdpPacketInfo. The test explicitly sets per_packet_options_ to mark ECT(0) after the handshake.
When receiving ACK_ECN, the results are reported to QuicConnection in OnAckFrameEnd(), which then just stores them in a new data structure QuicEcnCounts.
Protected by FLAGS_quic_reloadable_flag_quic_receive_ecn.
PiperOrigin-RevId: 501596181
diff --git a/quiche/quic/core/quic_received_packet_manager.cc b/quiche/quic/core/quic_received_packet_manager.cc
index bb7b87d..0486618 100644
--- a/quiche/quic/core/quic_received_packet_manager.cc
+++ b/quiche/quic/core/quic_received_packet_manager.cc
@@ -10,7 +10,9 @@
#include "quiche/quic/core/congestion_control/rtt_stats.h"
#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_types.h"
#include "quiche/quic/platform/api/quic_bug_tracker.h"
#include "quiche/quic/platform/api/quic_flags.h"
#include "quiche/quic/platform/api/quic_logging.h"
@@ -70,7 +72,8 @@
}
void QuicReceivedPacketManager::RecordPacketReceived(
- const QuicPacketHeader& header, QuicTime receipt_time) {
+ const QuicPacketHeader& header, QuicTime receipt_time,
+ const QuicEcnCodepoint ecn) {
const QuicPacketNumber packet_number = header.packet_number;
QUICHE_DCHECK(IsAwaitingPacket(packet_number))
<< " packet_number:" << packet_number;
@@ -119,6 +122,27 @@
}
}
+ if (GetQuicRestartFlag(quic_receive_ecn) && ecn != ECN_NOT_ECT) {
+ QUIC_RESTART_FLAG_COUNT_N(quic_receive_ecn, 1, 3);
+ if (!ack_frame_.ecn_counters.has_value()) {
+ ack_frame_.ecn_counters = QuicEcnCounts();
+ }
+ switch (ecn) {
+ case ECN_NOT_ECT:
+ QUICHE_NOTREACHED();
+ break; // It's impossible to get here, but the compiler complains.
+ case ECN_ECT0:
+ ack_frame_.ecn_counters->ect0++;
+ break;
+ case ECN_ECT1:
+ ack_frame_.ecn_counters->ect1++;
+ break;
+ case ECN_CE:
+ ack_frame_.ecn_counters->ce++;
+ break;
+ }
+ }
+
if (least_received_packet_number_.IsInitialized()) {
least_received_packet_number_ =
std::min(least_received_packet_number_, packet_number);