From 69cbb6ec5bac8191869c98879089aa5bb0875ac6 Mon Sep 17 00:00:00 2001 From: Marten Seemann Date: Mon, 4 Aug 2025 10:00:02 +0200 Subject: [PATCH] qlog: add support for ACK_FREQUENCY and IMMEDIATE_ACK frames (#5276) --- logging/frame.go | 4 ++++ qlog/frame.go | 16 ++++++++++++++++ qlog/frame_test.go | 27 +++++++++++++++++++++++++++ 3 files changed, 47 insertions(+) diff --git a/logging/frame.go b/logging/frame.go index 9a055db35..51732250b 100644 --- a/logging/frame.go +++ b/logging/frame.go @@ -44,6 +44,10 @@ type ( StreamsBlockedFrame = wire.StreamsBlockedFrame // A StreamDataBlockedFrame is a STREAM_DATA_BLOCKED frame. StreamDataBlockedFrame = wire.StreamDataBlockedFrame + // An AckFrequencyFrame is an ACK_FREQUENCY frame. + AckFrequencyFrame = wire.AckFrequencyFrame + // An ImmediateAckFrame is an IMMEDIATE_ACK frame. + ImmediateAckFrame = wire.ImmediateAckFrame ) // A CryptoFrame is a CRYPTO frame. diff --git a/qlog/frame.go b/qlog/frame.go index 6f04deb36..5b1d4c42f 100644 --- a/qlog/frame.go +++ b/qlog/frame.go @@ -59,6 +59,10 @@ func (f frame) MarshalJSONObject(enc *gojay.Encoder) { marshalHandshakeDoneFrame(enc, frame) case *logging.DatagramFrame: marshalDatagramFrame(enc, frame) + case *logging.AckFrequencyFrame: + marshalAckFrequencyFrame(enc, frame) + case *logging.ImmediateAckFrame: + marshalImmediateAckFrame(enc, frame) default: panic("unknown frame type") } @@ -232,3 +236,15 @@ func marshalDatagramFrame(enc *gojay.Encoder, f *logging.DatagramFrame) { enc.StringKey("frame_type", "datagram") enc.Int64Key("length", int64(f.Length)) } + +func marshalAckFrequencyFrame(enc *gojay.Encoder, f *logging.AckFrequencyFrame) { + enc.StringKey("frame_type", "ack_frequency") + enc.Uint64Key("sequence_number", f.SequenceNumber) + enc.Uint64Key("ack_eliciting_threshold", f.AckElicitingThreshold) + enc.Float64Key("request_max_ack_delay", milliseconds(f.RequestMaxAckDelay)) + enc.Uint64Key("reordering_threshold", uint64(f.ReorderingThreshold)) +} + +func marshalImmediateAckFrame(enc *gojay.Encoder, _ *logging.ImmediateAckFrame) { + enc.StringKey("frame_type", "immediate_ack") +} diff --git a/qlog/frame_test.go b/qlog/frame_test.go index 5b5e3c3c9..2bcc48e2c 100644 --- a/qlog/frame_test.go +++ b/qlog/frame_test.go @@ -137,6 +137,33 @@ func TestResetStreamAtFrame(t *testing.T) { ) } +func TestAckFrequencyFrame(t *testing.T) { + check(t, + &logging.AckFrequencyFrame{ + SequenceNumber: 1337, + AckElicitingThreshold: 123, + RequestMaxAckDelay: 42 * time.Millisecond, + ReorderingThreshold: 1234, + }, + map[string]interface{}{ + "frame_type": "ack_frequency", + "sequence_number": 1337, + "ack_eliciting_threshold": 123, + "request_max_ack_delay": 42, + "reordering_threshold": 1234, + }, + ) +} + +func TestImmediateAckFrame(t *testing.T) { + check(t, + &logging.ImmediateAckFrame{}, + map[string]interface{}{ + "frame_type": "immediate_ack", + }, + ) +} + func TestStopSendingFrame(t *testing.T) { check(t, &logging.StopSendingFrame{