]> git.feebdaed.xyz Git - 0xmirror/quic-go.git/commitdiff
qlog the datagram_id for long header and coalesced packets (#5455)
authorMarten Seemann <martenseemann@gmail.com>
Sat, 22 Nov 2025 01:50:59 +0000 (09:50 +0800)
committerGitHub <noreply@github.com>
Sat, 22 Nov 2025 01:50:59 +0000 (02:50 +0100)
* simplify logging of short header packets

No functional change expected.

* qlog: add datagram_id field to packet evens

* qlog the datagram_id for long header and coalesced packets

No datagram_id is logged for short header packets.

connection.go
connection_logging.go
connection_test.go
qlog/event.go
qlog/event_test.go
qlog/types.go
qlog/types_test.go

index faf9f1101cefb5d98dd919f5dac014556e42a884..adaad4a6d67e5ff0f601b2334beb8ba90a063bae 100644 (file)
@@ -57,6 +57,11 @@ type receivedPacket struct {
        info packetInfo // only valid if the contained IP address is valid
 }
 
+type receivedPacketWithDatagramID struct {
+       receivedPacket
+       datagramID qlog.DatagramID
+}
+
 func (p *receivedPacket) Size() protocol.ByteCount { return protocol.ByteCount(len(p.data)) }
 
 func (p *receivedPacket) Clone() *receivedPacket {
@@ -183,8 +188,8 @@ type Conn struct {
        ctxCancel             context.CancelCauseFunc
        handshakeCompleteChan chan struct{}
 
-       undecryptablePackets          []receivedPacket // undecryptable packets, waiting for a change in encryption level
-       undecryptablePacketsToProcess []receivedPacket
+       undecryptablePackets          []receivedPacketWithDatagramID // undecryptable packets, waiting for a change in encryption level
+       undecryptablePacketsToProcess []receivedPacketWithDatagramID
 
        earlyConnReadyChan chan struct{}
        sentFirstPacket    bool
@@ -615,7 +620,7 @@ runLoop:
                        queue := c.undecryptablePacketsToProcess
                        c.undecryptablePacketsToProcess = nil
                        for _, p := range queue {
-                               processed, err := c.handleOnePacket(p)
+                               processed, err := c.handleOnePacket(p.receivedPacket, p.datagramID)
                                if err != nil {
                                        c.setCloseError(&closeError{err: err})
                                        break runLoop
@@ -1006,7 +1011,11 @@ func (c *Conn) handlePackets() (wasProcessed bool, _ error) {
                hasMorePackets = !c.receivedPackets.Empty()
                c.receivedPacketMx.Unlock()
 
-               processed, err := c.handleOnePacket(p)
+               var datagramID qlog.DatagramID
+               if c.qlogger != nil && wire.IsLongHeaderPacket(p.data[0]) {
+                       datagramID = qlog.CalculateDatagramID(p.data)
+               }
+               processed, err := c.handleOnePacket(p, datagramID)
                if err != nil {
                        return false, err
                }
@@ -1030,7 +1039,7 @@ func (c *Conn) handlePackets() (wasProcessed bool, _ error) {
        return wasProcessed, nil
 }
 
-func (c *Conn) handleOnePacket(rp receivedPacket) (wasProcessed bool, _ error) {
+func (c *Conn) handleOnePacket(rp receivedPacket, datagramID qlog.DatagramID) (wasProcessed bool, _ error) {
        c.sentPacketHandler.ReceivedBytes(rp.Size(), rp.rcvTime)
 
        if wire.IsVersionNegotiationPacket(rp.data) {
@@ -1051,8 +1060,9 @@ func (c *Conn) handleOnePacket(rp receivedPacket) (wasProcessed bool, _ error) {
                        if err != nil {
                                if c.qlogger != nil {
                                        c.qlogger.RecordEvent(qlog.PacketDropped{
-                                               Raw:     qlog.RawInfo{Length: len(data)},
-                                               Trigger: qlog.PacketDropHeaderParseError,
+                                               Raw:        qlog.RawInfo{Length: len(data)},
+                                               DatagramID: datagramID,
+                                               Trigger:    qlog.PacketDropHeaderParseError,
                                        })
                                }
                                c.logger.Debugf("error parsing packet, couldn't parse connection ID: %s", err)
@@ -1061,9 +1071,10 @@ func (c *Conn) handleOnePacket(rp receivedPacket) (wasProcessed bool, _ error) {
                        if destConnID != lastConnID {
                                if c.qlogger != nil {
                                        c.qlogger.RecordEvent(qlog.PacketDropped{
-                                               Header:  qlog.PacketHeader{DestConnectionID: destConnID},
-                                               Raw:     qlog.RawInfo{Length: len(data)},
-                                               Trigger: qlog.PacketDropUnknownConnectionID,
+                                               Header:     qlog.PacketHeader{DestConnectionID: destConnID},
+                                               Raw:        qlog.RawInfo{Length: len(data)},
+                                               DatagramID: datagramID,
+                                               Trigger:    qlog.PacketDropUnknownConnectionID,
                                        })
                                }
                                c.logger.Debugf("coalesced packet has different destination connection ID: %s, expected %s", destConnID, lastConnID)
@@ -1077,14 +1088,16 @@ func (c *Conn) handleOnePacket(rp receivedPacket) (wasProcessed bool, _ error) {
                                if c.qlogger != nil {
                                        if err == wire.ErrUnsupportedVersion {
                                                c.qlogger.RecordEvent(qlog.PacketDropped{
-                                                       Header:  qlog.PacketHeader{Version: hdr.Version},
-                                                       Raw:     qlog.RawInfo{Length: len(data)},
-                                                       Trigger: qlog.PacketDropUnsupportedVersion,
+                                                       Header:     qlog.PacketHeader{Version: hdr.Version},
+                                                       Raw:        qlog.RawInfo{Length: len(data)},
+                                                       DatagramID: datagramID,
+                                                       Trigger:    qlog.PacketDropUnsupportedVersion,
                                                })
                                        } else {
                                                c.qlogger.RecordEvent(qlog.PacketDropped{
-                                                       Raw:     qlog.RawInfo{Length: len(data)},
-                                                       Trigger: qlog.PacketDropHeaderParseError,
+                                                       Raw:        qlog.RawInfo{Length: len(data)},
+                                                       DatagramID: datagramID,
+                                                       Trigger:    qlog.PacketDropHeaderParseError,
                                                })
                                        }
                                }
@@ -1096,8 +1109,9 @@ func (c *Conn) handleOnePacket(rp receivedPacket) (wasProcessed bool, _ error) {
                        if hdr.Version != c.version {
                                if c.qlogger != nil {
                                        c.qlogger.RecordEvent(qlog.PacketDropped{
-                                               Raw:     qlog.RawInfo{Length: len(data)},
-                                               Trigger: qlog.PacketDropUnexpectedVersion,
+                                               Raw:        qlog.RawInfo{Length: len(data)},
+                                               DatagramID: datagramID,
+                                               Trigger:    qlog.PacketDropUnexpectedVersion,
                                        })
                                }
                                c.logger.Debugf("Dropping packet with version %x. Expected %x.", hdr.Version, c.version)
@@ -1116,7 +1130,7 @@ func (c *Conn) handleOnePacket(rp receivedPacket) (wasProcessed bool, _ error) {
 
                        p.data = packetData
 
-                       processed, err := c.handleLongHeaderPacket(p, hdr)
+                       processed, err := c.handleLongHeaderPacket(p, hdr, datagramID)
                        if err != nil {
                                return false, err
                        }
@@ -1128,7 +1142,7 @@ func (c *Conn) handleOnePacket(rp receivedPacket) (wasProcessed bool, _ error) {
                        if counter > 0 {
                                p.buffer.Split()
                        }
-                       processed, err := c.handleShortHeaderPacket(p, counter > 0)
+                       processed, err := c.handleShortHeaderPacket(p, counter > 0, datagramID)
                        if err != nil {
                                return false, err
                        }
@@ -1144,7 +1158,11 @@ func (c *Conn) handleOnePacket(rp receivedPacket) (wasProcessed bool, _ error) {
        return wasProcessed, nil
 }
 
-func (c *Conn) handleShortHeaderPacket(p receivedPacket, isCoalesced bool) (wasProcessed bool, _ error) {
+func (c *Conn) handleShortHeaderPacket(
+       p receivedPacket,
+       isCoalesced bool,
+       datagramID qlog.DatagramID, // only for logging
+) (wasProcessed bool, _ error) {
        var wasQueued bool
 
        defer func() {
@@ -1161,8 +1179,9 @@ func (c *Conn) handleShortHeaderPacket(p receivedPacket, isCoalesced bool) (wasP
                                PacketType:   qlog.PacketType1RTT,
                                PacketNumber: protocol.InvalidPacketNumber,
                        },
-                       Raw:     qlog.RawInfo{Length: len(p.data)},
-                       Trigger: qlog.PacketDropHeaderParseError,
+                       Raw:        qlog.RawInfo{Length: len(p.data)},
+                       DatagramID: datagramID,
+                       Trigger:    qlog.PacketDropHeaderParseError,
                })
                return false, nil
        }
@@ -1179,7 +1198,7 @@ func (c *Conn) handleShortHeaderPacket(p receivedPacket, isCoalesced bool) (wasP
                                return false, &StatelessResetError{}
                        }
                }
-               wasQueued, err = c.handleUnpackError(err, p, qlog.PacketType1RTT)
+               wasQueued, err = c.handleUnpackError(err, p, qlog.PacketType1RTT, datagramID)
                return false, err
        }
        c.largestRcvdAppData = max(c.largestRcvdAppData, pn)
@@ -1197,8 +1216,9 @@ func (c *Conn) handleShortHeaderPacket(p receivedPacket, isCoalesced bool) (wasP
                                        PacketType:   qlog.PacketType1RTT,
                                        PacketNumber: pn,
                                },
-                               Raw:     qlog.RawInfo{Length: int(p.Size())},
-                               Trigger: qlog.PacketDropDuplicate,
+                               Raw:        qlog.RawInfo{Length: int(p.Size())},
+                               DatagramID: datagramID,
+                               Trigger:    qlog.PacketDropDuplicate,
                        })
                }
                return false, nil
@@ -1218,8 +1238,9 @@ func (c *Conn) handleShortHeaderPacket(p receivedPacket, isCoalesced bool) (wasP
                                        Length:        int(p.Size()),
                                        PayloadLength: int(p.Size() - wire.ShortHeaderLen(destConnID, pnLen)),
                                },
-                               Frames: frames,
-                               ECN:    toQlogECN(p.ecn),
+                               DatagramID: datagramID,
+                               Frames:     frames,
+                               ECN:        toQlogECN(p.ecn),
                        })
                }
        }
@@ -1251,7 +1272,7 @@ func (c *Conn) handleShortHeaderPacket(p receivedPacket, isCoalesced bool) (wasP
                        return true, err
                }
                c.logger.Debugf("sending path probe packet to %s", p.remoteAddr)
-               c.logShortHeaderPacket(probe.DestConnID, probe.Ack, probe.Frames, probe.StreamFrames, probe.PacketNumber, probe.PacketNumberLen, probe.KeyPhase, protocol.ECNNon, buf.Len(), false)
+               c.logShortHeaderPacketWithDatagramID(probe, protocol.ECNNon, buf.Len(), false, datagramID)
                c.registerPackedShortHeaderPacket(probe, protocol.ECNNon, p.rcvTime)
                c.sendQueue.SendProbe(buf, p.remoteAddr)
        }
@@ -1275,7 +1296,7 @@ func (c *Conn) handleShortHeaderPacket(p receivedPacket, isCoalesced bool) (wasP
        return true, nil
 }
 
-func (c *Conn) handleLongHeaderPacket(p receivedPacket, hdr *wire.Header) (wasProcessed bool, _ error) {
+func (c *Conn) handleLongHeaderPacket(p receivedPacket, hdr *wire.Header, datagramID qlog.DatagramID) (wasProcessed bool, _ error) {
        var wasQueued bool
 
        defer func() {
@@ -1298,8 +1319,9 @@ func (c *Conn) handleLongHeaderPacket(p receivedPacket, hdr *wire.Header) (wasPr
                                        PacketType:   qlog.PacketTypeInitial,
                                        PacketNumber: protocol.InvalidPacketNumber,
                                },
-                               Raw:     qlog.RawInfo{Length: int(p.Size())},
-                               Trigger: qlog.PacketDropUnknownConnectionID,
+                               Raw:        qlog.RawInfo{Length: int(p.Size())},
+                               DatagramID: datagramID,
+                               Trigger:    qlog.PacketDropUnknownConnectionID,
                        })
                }
                c.logger.Debugf("Dropping Initial packet (%d bytes) with unexpected source connection ID: %s (expected %s)", p.Size(), hdr.SrcConnectionID, c.handshakeDestConnID)
@@ -1313,8 +1335,9 @@ func (c *Conn) handleLongHeaderPacket(p receivedPacket, hdr *wire.Header) (wasPr
                                        PacketType:   qlog.PacketType0RTT,
                                        PacketNumber: protocol.InvalidPacketNumber,
                                },
-                               Raw:     qlog.RawInfo{Length: int(p.Size())},
-                               Trigger: qlog.PacketDropUnexpectedPacket,
+                               Raw:        qlog.RawInfo{Length: int(p.Size())},
+                               DatagramID: datagramID,
+                               Trigger:    qlog.PacketDropUnexpectedPacket,
                        })
                }
                return false, nil
@@ -1322,7 +1345,7 @@ func (c *Conn) handleLongHeaderPacket(p receivedPacket, hdr *wire.Header) (wasPr
 
        packet, err := c.unpacker.UnpackLongHeader(hdr, p.data)
        if err != nil {
-               wasQueued, err = c.handleUnpackError(err, p, toQlogPacketType(hdr.Type))
+               wasQueued, err = c.handleUnpackError(err, p, toQlogPacketType(hdr.Type), datagramID)
                return false, err
        }
 
@@ -1342,20 +1365,21 @@ func (c *Conn) handleLongHeaderPacket(p receivedPacket, hdr *wire.Header) (wasPr
                                        PacketNumber:     pn,
                                        Version:          packet.hdr.Version,
                                },
-                               Raw:     qlog.RawInfo{Length: int(p.Size()), PayloadLength: int(packet.hdr.Length)},
-                               Trigger: qlog.PacketDropDuplicate,
+                               Raw:        qlog.RawInfo{Length: int(p.Size()), PayloadLength: int(packet.hdr.Length)},
+                               DatagramID: datagramID,
+                               Trigger:    qlog.PacketDropDuplicate,
                        })
                }
                return false, nil
        }
 
-       if err := c.handleUnpackedLongHeaderPacket(packet, p.ecn, p.rcvTime, p.Size()); err != nil {
+       if err := c.handleUnpackedLongHeaderPacket(packet, p.ecn, p.rcvTime, datagramID, p.Size()); err != nil {
                return false, err
        }
        return true, nil
 }
 
-func (c *Conn) handleUnpackError(err error, p receivedPacket, pt qlog.PacketType) (wasQueued bool, _ error) {
+func (c *Conn) handleUnpackError(err error, p receivedPacket, pt qlog.PacketType, datagramID qlog.DatagramID) (wasQueued bool, _ error) {
        switch err {
        case handshake.ErrKeysDropped:
                if c.qlogger != nil {
@@ -1366,8 +1390,9 @@ func (c *Conn) handleUnpackError(err error, p receivedPacket, pt qlog.PacketType
                                        DestConnectionID: connID,
                                        PacketNumber:     protocol.InvalidPacketNumber,
                                },
-                               Raw:     qlog.RawInfo{Length: int(p.Size())},
-                               Trigger: qlog.PacketDropKeyUnavailable,
+                               Raw:        qlog.RawInfo{Length: int(p.Size())},
+                               DatagramID: datagramID,
+                               Trigger:    qlog.PacketDropKeyUnavailable,
                        })
                }
                c.logger.Debugf("Dropping %s packet (%d bytes) because we already dropped the keys.", pt, p.Size())
@@ -1375,7 +1400,7 @@ func (c *Conn) handleUnpackError(err error, p receivedPacket, pt qlog.PacketType
        case handshake.ErrKeysNotYetAvailable:
                // Sealer for this encryption level not yet available.
                // Try again later.
-               c.tryQueueingUndecryptablePacket(p, pt)
+               c.tryQueueingUndecryptablePacket(p, pt, datagramID)
                return true, nil
        case wire.ErrInvalidReservedBits:
                return false, &qerr.TransportError{
@@ -1392,8 +1417,9 @@ func (c *Conn) handleUnpackError(err error, p receivedPacket, pt qlog.PacketType
                                        DestConnectionID: connID,
                                        PacketNumber:     protocol.InvalidPacketNumber,
                                },
-                               Raw:     qlog.RawInfo{Length: int(p.Size())},
-                               Trigger: qlog.PacketDropPayloadDecryptError,
+                               Raw:        qlog.RawInfo{Length: int(p.Size())},
+                               DatagramID: datagramID,
+                               Trigger:    qlog.PacketDropPayloadDecryptError,
                        })
                }
                c.logger.Debugf("Dropping %s packet (%d bytes) that could not be unpacked. Error: %s", pt, p.Size(), err)
@@ -1410,8 +1436,9 @@ func (c *Conn) handleUnpackError(err error, p receivedPacket, pt qlog.PacketType
                                                DestConnectionID: connID,
                                                PacketNumber:     protocol.InvalidPacketNumber,
                                        },
-                                       Raw:     qlog.RawInfo{Length: int(p.Size())},
-                                       Trigger: qlog.PacketDropHeaderParseError,
+                                       Raw:        qlog.RawInfo{Length: int(p.Size())},
+                                       DatagramID: datagramID,
+                                       Trigger:    qlog.PacketDropHeaderParseError,
                                })
                        }
                        c.logger.Debugf("Dropping %s packet (%d bytes) for which we couldn't unpack the header. Error: %s", pt, p.Size(), err)
@@ -1607,6 +1634,7 @@ func (c *Conn) handleUnpackedLongHeaderPacket(
        packet *unpackedPacket,
        ecn protocol.ECN,
        rcvTime monotime.Time,
+       datagramID qlog.DatagramID, // only for logging
        packetSize protocol.ByteCount, // only for logging
 ) error {
        if !c.receivedFirstPacket {
@@ -1692,8 +1720,9 @@ func (c *Conn) handleUnpackedLongHeaderPacket(
                                        Length:        int(packetSize),
                                        PayloadLength: int(packet.hdr.Length),
                                },
-                               Frames: frames,
-                               ECN:    toQlogECN(ecn),
+                               DatagramID: datagramID,
+                               Frames:     frames,
+                               ECN:        toQlogECN(ecn),
                        })
                }
        }
@@ -1916,9 +1945,14 @@ func (c *Conn) handlePacket(p receivedPacket) {
        // the channel size, protocol.MaxConnUnprocessedPackets
        if c.receivedPackets.Len() >= protocol.MaxConnUnprocessedPackets {
                if c.qlogger != nil {
+                       var datagramID qlog.DatagramID
+                       if wire.IsLongHeaderPacket(p.data[0]) {
+                               datagramID = qlog.CalculateDatagramID(p.data)
+                       }
                        c.qlogger.RecordEvent(qlog.PacketDropped{
-                               Raw:     qlog.RawInfo{Length: int(p.Size())},
-                               Trigger: qlog.PacketDropDOSPrevention,
+                               Raw:        qlog.RawInfo{Length: int(p.Size())},
+                               DatagramID: datagramID,
+                               Trigger:    qlog.PacketDropDOSPrevention,
                        })
                }
                c.receivedPacketMx.Unlock()
@@ -2456,7 +2490,7 @@ func (c *Conn) sendPackets(now monotime.Time) error {
                                        return err
                                }
                                c.logger.Debugf("sending path probe packet from %s", c.LocalAddr())
-                               c.logShortHeaderPacket(probe.DestConnID, probe.Ack, probe.Frames, probe.StreamFrames, probe.PacketNumber, probe.PacketNumberLen, probe.KeyPhase, protocol.ECNNon, buf.Len(), false)
+                               c.logShortHeaderPacket(probe, protocol.ECNNon, buf.Len())
                                c.registerPackedShortHeaderPacket(probe, protocol.ECNNon, now)
                                tr.WriteTo(buf.Data, c.conn.RemoteAddr())
                                // There's (likely) more data to send. Loop around again.
@@ -2477,7 +2511,7 @@ func (c *Conn) sendPackets(now monotime.Time) error {
                        return err
                }
                ecn := c.sentPacketHandler.ECNMode(true)
-               c.logShortHeaderPacket(p.DestConnID, p.Ack, p.Frames, p.StreamFrames, p.PacketNumber, p.PacketNumberLen, p.KeyPhase, ecn, buf.Len(), false)
+               c.logShortHeaderPacket(p, ecn, buf.Len())
                c.registerPackedShortHeaderPacket(p, ecn, now)
                c.sendQueue.Send(buf, 0, ecn)
                // There's (likely) more data to send. Loop around again.
@@ -2646,7 +2680,7 @@ func (c *Conn) maybeSendAckOnlyPacket(now monotime.Time) error {
                }
                return err
        }
-       c.logShortHeaderPacket(p.DestConnID, p.Ack, p.Frames, p.StreamFrames, p.PacketNumber, p.PacketNumberLen, p.KeyPhase, ecn, buf.Len(), false)
+       c.logShortHeaderPacket(p, ecn, buf.Len())
        c.registerPackedShortHeaderPacket(p, ecn, now)
        c.sendQueue.Send(buf, 0, ecn)
        return nil
@@ -2700,7 +2734,7 @@ func (c *Conn) appendOneShortHeaderPacket(buf *packetBuffer, maxSize protocol.By
                return 0, err
        }
        size := buf.Len() - startLen
-       c.logShortHeaderPacket(p.DestConnID, p.Ack, p.Frames, p.StreamFrames, p.PacketNumber, p.PacketNumberLen, p.KeyPhase, ecn, size, false)
+       c.logShortHeaderPacket(p, ecn, size)
        c.registerPackedShortHeaderPacket(p, ecn, now)
        return size, nil
 }
@@ -2920,7 +2954,7 @@ func (c *Conn) scheduleSending() {
 
 // tryQueueingUndecryptablePacket queues a packet for which we're missing the decryption keys.
 // The qlogevents.PacketType is only used for logging purposes.
-func (c *Conn) tryQueueingUndecryptablePacket(p receivedPacket, pt qlog.PacketType) {
+func (c *Conn) tryQueueingUndecryptablePacket(p receivedPacket, pt qlog.PacketType, datagramID qlog.DatagramID) {
        if c.handshakeComplete {
                panic("shouldn't queue undecryptable packets after handshake completion")
        }
@@ -2931,8 +2965,9 @@ func (c *Conn) tryQueueingUndecryptablePacket(p receivedPacket, pt qlog.PacketTy
                                        PacketType:   pt,
                                        PacketNumber: protocol.InvalidPacketNumber,
                                },
-                               Raw:     qlog.RawInfo{Length: int(p.Size())},
-                               Trigger: qlog.PacketDropDOSPrevention,
+                               Raw:        qlog.RawInfo{Length: int(p.Size())},
+                               DatagramID: datagramID,
+                               Trigger:    qlog.PacketDropDOSPrevention,
                        })
                }
                c.logger.Infof("Dropping undecryptable packet (%d bytes). Undecryptable packet queue full.", p.Size())
@@ -2945,10 +2980,11 @@ func (c *Conn) tryQueueingUndecryptablePacket(p receivedPacket, pt qlog.PacketTy
                                PacketType:   pt,
                                PacketNumber: protocol.InvalidPacketNumber,
                        },
-                       Raw: qlog.RawInfo{Length: int(p.Size())},
+                       Raw:        qlog.RawInfo{Length: int(p.Size())},
+                       DatagramID: datagramID,
                })
        }
-       c.undecryptablePackets = append(c.undecryptablePackets, p)
+       c.undecryptablePackets = append(c.undecryptablePackets, receivedPacketWithDatagramID{receivedPacket: p, datagramID: datagramID})
 }
 
 func (c *Conn) queueControlFrame(f wire.Frame) {
index 0c6221d5b401df679329ae5e885b5dde92316418..c828c8be021d8e4c6b0a358e14bb3b26a861c1f0 100644 (file)
@@ -5,7 +5,6 @@ import (
        "net/netip"
        "slices"
 
-       "github.com/quic-go/quic-go/internal/ackhandler"
        "github.com/quic-go/quic-go/internal/protocol"
        "github.com/quic-go/quic-go/internal/wire"
        "github.com/quic-go/quic-go/qlog"
@@ -58,7 +57,7 @@ func toQlogAckFrame(f *wire.AckFrame) *qlog.AckFrame {
        return ack
 }
 
-func (c *Conn) logLongHeaderPacket(p *longHeaderPacket, ecn protocol.ECN) {
+func (c *Conn) logLongHeaderPacket(p *longHeaderPacket, ecn protocol.ECN, datagramID qlog.DatagramID) {
        // quic-go logging
        if c.logger.Debug() {
                p.header.Log(c.logger)
@@ -102,91 +101,85 @@ func (c *Conn) logLongHeaderPacket(p *longHeaderPacket, ecn protocol.ECN) {
                                Length:        int(p.length),
                                PayloadLength: int(p.header.Length),
                        },
-                       Frames: frames,
-                       ECN:    toQlogECN(ecn),
+                       DatagramID: datagramID,
+                       Frames:     frames,
+                       ECN:        toQlogECN(ecn),
                })
        }
 }
 
-func (c *Conn) logShortHeaderPacket(
-       destConnID protocol.ConnectionID,
-       ackFrame *wire.AckFrame,
-       frames []ackhandler.Frame,
-       streamFrames []ackhandler.StreamFrame,
-       pn protocol.PacketNumber,
-       pnLen protocol.PacketNumberLen,
-       kp protocol.KeyPhaseBit,
-       ecn protocol.ECN,
-       size protocol.ByteCount,
-       isCoalesced bool,
-) {
+func (c *Conn) logShortHeaderPacket(p shortHeaderPacket, ecn protocol.ECN, size protocol.ByteCount) {
+       c.logShortHeaderPacketWithDatagramID(p, ecn, size, false, 0)
+}
+
+func (c *Conn) logShortHeaderPacketWithDatagramID(p shortHeaderPacket, ecn protocol.ECN, size protocol.ByteCount, isCoalesced bool, datagramID qlog.DatagramID) {
        if c.logger.Debug() && !isCoalesced {
-               c.logger.Debugf("-> Sending packet %d (%d bytes) for connection %s, 1-RTT (ECN: %s)", pn, size, c.logID, ecn)
+               c.logger.Debugf("-> Sending packet %d (%d bytes) for connection %s, 1-RTT (ECN: %s)", p.PacketNumber, size, c.logID, ecn)
        }
        // quic-go logging
        if c.logger.Debug() {
-               wire.LogShortHeader(c.logger, destConnID, pn, pnLen, kp)
-               if ackFrame != nil {
-                       wire.LogFrame(c.logger, ackFrame, true)
+               wire.LogShortHeader(c.logger, p.DestConnID, p.PacketNumber, p.PacketNumberLen, p.KeyPhase)
+               if p.Ack != nil {
+                       wire.LogFrame(c.logger, p.Ack, true)
                }
-               for _, f := range frames {
+               for _, f := range p.Frames {
                        wire.LogFrame(c.logger, f.Frame, true)
                }
-               for _, f := range streamFrames {
+               for _, f := range p.StreamFrames {
                        wire.LogFrame(c.logger, f.Frame, true)
                }
        }
 
        // tracing
        if c.qlogger != nil {
-               numFrames := len(frames) + len(streamFrames)
-               if ackFrame != nil {
+               numFrames := len(p.Frames) + len(p.StreamFrames)
+               if p.Ack != nil {
                        numFrames++
                }
                fs := make([]qlog.Frame, 0, numFrames)
-               if ackFrame != nil {
-                       fs = append(fs, toQlogFrame(ackFrame))
+               if p.Ack != nil {
+                       fs = append(fs, toQlogFrame(p.Ack))
                }
-               for _, f := range frames {
+               for _, f := range p.Frames {
                        fs = append(fs, toQlogFrame(f.Frame))
                }
-               for _, f := range streamFrames {
+               for _, f := range p.StreamFrames {
                        fs = append(fs, toQlogFrame(f.Frame))
                }
                c.qlogger.RecordEvent(qlog.PacketSent{
                        Header: qlog.PacketHeader{
                                PacketType:       qlog.PacketType1RTT,
-                               KeyPhaseBit:      kp,
-                               PacketNumber:     pn,
+                               KeyPhaseBit:      p.KeyPhase,
+                               PacketNumber:     p.PacketNumber,
                                Version:          c.version,
-                               DestConnectionID: destConnID,
+                               DestConnectionID: p.DestConnID,
                        },
                        Raw: qlog.RawInfo{
                                Length:        int(size),
-                               PayloadLength: int(size - wire.ShortHeaderLen(destConnID, pnLen)),
+                               PayloadLength: int(size - wire.ShortHeaderLen(p.DestConnID, p.PacketNumberLen)),
                        },
-                       Frames: fs,
-                       ECN:    toQlogECN(ecn),
+                       DatagramID: datagramID,
+                       Frames:     fs,
+                       ECN:        toQlogECN(ecn),
                })
        }
 }
 
 func (c *Conn) logCoalescedPacket(packet *coalescedPacket, ecn protocol.ECN) {
+       var datagramID qlog.DatagramID
+       if c.qlogger != nil {
+               datagramID = qlog.CalculateDatagramID(packet.buffer.Data)
+       }
        if c.logger.Debug() {
                // There's a short period between dropping both Initial and Handshake keys and completion of the handshake,
                // during which we might call PackCoalescedPacket but just pack a short header packet.
                if len(packet.longHdrPackets) == 0 && packet.shortHdrPacket != nil {
-                       c.logShortHeaderPacket(
-                               packet.shortHdrPacket.DestConnID,
-                               packet.shortHdrPacket.Ack,
-                               packet.shortHdrPacket.Frames,
-                               packet.shortHdrPacket.StreamFrames,
-                               packet.shortHdrPacket.PacketNumber,
-                               packet.shortHdrPacket.PacketNumberLen,
-                               packet.shortHdrPacket.KeyPhase,
+                       c.logShortHeaderPacketWithDatagramID(
+                               *packet.shortHdrPacket,
                                ecn,
                                packet.shortHdrPacket.Length,
                                false,
+                               datagramID,
                        )
                        return
                }
@@ -197,10 +190,10 @@ func (c *Conn) logCoalescedPacket(packet *coalescedPacket, ecn protocol.ECN) {
                }
        }
        for _, p := range packet.longHdrPackets {
-               c.logLongHeaderPacket(p, ecn)
+               c.logLongHeaderPacket(p, ecn, datagramID)
        }
        if p := packet.shortHdrPacket; p != nil {
-               c.logShortHeaderPacket(p.DestConnID, p.Ack, p.Frames, p.StreamFrames, p.PacketNumber, p.PacketNumberLen, p.KeyPhase, ecn, p.Length, true)
+               c.logShortHeaderPacketWithDatagramID(*p, ecn, p.Length, true, datagramID)
        }
 }
 
index 3acc73791c818cbf1058abb875e33b0c5f6a1615..99c328853ce5f88eb92b2df3c510e532f58e45bb 100644 (file)
@@ -409,7 +409,7 @@ func TestConnectionServerInvalidPackets(t *testing.T) {
                        }},
                        make([]byte, 16), /* Retry integrity tag */
                )
-               wasProcessed, err := tc.conn.handleOnePacket(p)
+               wasProcessed, err := tc.conn.handleOnePacket(p, 0)
                require.NoError(t, err)
                require.False(t, wasProcessed)
                require.Equal(t,
@@ -439,7 +439,7 @@ func TestConnectionServerInvalidPackets(t *testing.T) {
                        protocol.ArbitraryLenConnectionID(tc.conn.origDestConnID.Bytes()),
                        []Version{Version1},
                )
-               wasProcessed, err := tc.conn.handleOnePacket(receivedPacket{data: b, buffer: getPacketBuffer()})
+               wasProcessed, err := tc.conn.handleOnePacket(receivedPacket{data: b, buffer: getPacketBuffer()}, 0)
                require.NoError(t, err)
                require.False(t, wasProcessed)
                require.Equal(t,
@@ -467,15 +467,16 @@ func TestConnectionServerInvalidPackets(t *testing.T) {
                        },
                        nil,
                )
-               wasProcessed, err := tc.conn.handleOnePacket(p)
+               wasProcessed, err := tc.conn.handleOnePacket(p, 42)
                require.NoError(t, err)
                require.False(t, wasProcessed)
                require.Equal(t,
                        []qlogwriter.Event{
                                qlog.PacketDropped{
-                                       Header:  qlog.PacketHeader{Version: 1234},
-                                       Raw:     qlog.RawInfo{Length: int(p.Size())},
-                                       Trigger: qlog.PacketDropUnsupportedVersion,
+                                       Header:     qlog.PacketHeader{Version: 1234},
+                                       Raw:        qlog.RawInfo{Length: int(p.Size())},
+                                       DatagramID: 42,
+                                       Trigger:    qlog.PacketDropUnsupportedVersion,
                                },
                        },
                        eventRecorder.Events(qlog.PacketDropped{}),
@@ -496,15 +497,16 @@ func TestConnectionServerInvalidPackets(t *testing.T) {
                        nil,
                )
                p.data[0] ^= 0x40 // unset the QUIC bit
-               wasProcessed, err := tc.conn.handleOnePacket(p)
+               wasProcessed, err := tc.conn.handleOnePacket(p, 42)
                require.NoError(t, err)
                require.False(t, wasProcessed)
                require.Equal(t,
                        []qlogwriter.Event{
                                qlog.PacketDropped{
-                                       Header:  qlog.PacketHeader{},
-                                       Raw:     qlog.RawInfo{Length: int(p.Size())},
-                                       Trigger: qlog.PacketDropHeaderParseError,
+                                       Header:     qlog.PacketHeader{},
+                                       Raw:        qlog.RawInfo{Length: int(p.Size())},
+                                       DatagramID: 42,
+                                       Trigger:    qlog.PacketDropHeaderParseError,
                                },
                        },
                        eventRecorder.Events(qlog.PacketDropped{}),
@@ -525,7 +527,7 @@ func TestConnectionClientDrop0RTT(t *testing.T) {
                },
                nil,
        )
-       wasProcessed, err := tc.conn.handleOnePacket(p)
+       wasProcessed, err := tc.conn.handleOnePacket(p, 1234)
        require.NoError(t, err)
        require.False(t, wasProcessed)
        require.Equal(t,
@@ -535,8 +537,9 @@ func TestConnectionClientDrop0RTT(t *testing.T) {
                                        PacketType:   qlog.PacketType0RTT,
                                        PacketNumber: protocol.InvalidPacketNumber,
                                },
-                               Raw:     qlog.RawInfo{Length: int(p.Size())},
-                               Trigger: qlog.PacketDropUnexpectedPacket,
+                               Raw:        qlog.RawInfo{Length: int(p.Size())},
+                               DatagramID: 1234,
+                               Trigger:    qlog.PacketDropUnexpectedPacket,
                        },
                },
                eventRecorder.Events(qlog.PacketDropped{}),
@@ -584,7 +587,7 @@ func TestConnectionUnpacking(t *testing.T) {
                rph.EXPECT().ReceivedPacket(protocol.PacketNumber(0x1337), protocol.ECNCE, protocol.EncryptionInitial, rcvTime, false),
        )
 
-       wasProcessed, err := tc.conn.handleOnePacket(packet)
+       wasProcessed, err := tc.conn.handleOnePacket(packet, 42)
        require.NoError(t, err)
        require.True(t, wasProcessed)
        require.Equal(t,
@@ -596,9 +599,10 @@ func TestConnectionUnpacking(t *testing.T) {
                                        PacketNumber:     protocol.PacketNumber(0x1337),
                                        Version:          protocol.Version1,
                                },
-                               Frames: []qlog.Frame{},
-                               ECN:    qlog.ECNCE,
-                               Raw:    qlog.RawInfo{Length: int(packet.Size()), PayloadLength: 1},
+                               Frames:     []qlog.Frame{},
+                               ECN:        qlog.ECNCE,
+                               Raw:        qlog.RawInfo{Length: int(packet.Size()), PayloadLength: 1},
+                               DatagramID: 42,
                        },
                },
                eventRecorder.Events(qlog.PacketReceived{}, qlog.PacketDropped{}),
@@ -613,7 +617,7 @@ func TestConnectionUnpacking(t *testing.T) {
                hdr:             &unpackedHdr,
                data:            []byte{0}, // one PADDING frame
        }, nil)
-       wasProcessed, err = tc.conn.handleOnePacket(packet)
+       wasProcessed, err = tc.conn.handleOnePacket(packet, 43)
        require.NoError(t, err)
        require.False(t, wasProcessed)
        require.Equal(t,
@@ -625,8 +629,9 @@ func TestConnectionUnpacking(t *testing.T) {
                                        PacketNumber:     protocol.PacketNumber(0x1337),
                                        Version:          protocol.Version1,
                                },
-                               Raw:     qlog.RawInfo{Length: int(packet.Size()), PayloadLength: 1},
-                               Trigger: qlog.PacketDropDuplicate,
+                               Raw:        qlog.RawInfo{Length: int(packet.Size()), PayloadLength: 1},
+                               DatagramID: 43,
+                               Trigger:    qlog.PacketDropDuplicate,
                        },
                },
                eventRecorder.Events(qlog.PacketReceived{}, qlog.PacketDropped{}),
@@ -644,7 +649,7 @@ func TestConnectionUnpacking(t *testing.T) {
        unpacker.EXPECT().UnpackShortHeader(gomock.Any(), gomock.Any()).Return(
                protocol.PacketNumber(0x1337), protocol.PacketNumberLen2, protocol.KeyPhaseZero, []byte{0} /* PADDING */, nil,
        )
-       wasProcessed, err = tc.conn.handleOnePacket(packet)
+       wasProcessed, err = tc.conn.handleOnePacket(packet, 0)
        require.NoError(t, err)
        require.Equal(t,
                []qlogwriter.Event{
@@ -742,7 +747,7 @@ func TestConnectionUnpackCoalescedPacket(t *testing.T) {
                rph.EXPECT().ReceivedPacket(protocol.PacketNumber(1338), protocol.ECT1, protocol.EncryptionHandshake, rcvTime, true),
        )
        rph.EXPECT().DropPackets(protocol.EncryptionInitial)
-       wasProcessed, err := tc.conn.handleOnePacket(packet)
+       wasProcessed, err := tc.conn.handleOnePacket(packet, 42)
        require.NoError(t, err)
        require.True(t, wasProcessed)
 
@@ -755,9 +760,10 @@ func TestConnectionUnpackCoalescedPacket(t *testing.T) {
                                        PacketNumber:     protocol.PacketNumber(1337),
                                        Version:          protocol.Version1,
                                },
-                               Raw:    qlog.RawInfo{Length: int(firstPacketLen), PayloadLength: 1},
-                               Frames: []qlog.Frame{},
-                               ECN:    qlog.ECT1,
+                               Raw:        qlog.RawInfo{Length: int(firstPacketLen), PayloadLength: 1},
+                               DatagramID: 42,
+                               Frames:     []qlog.Frame{},
+                               ECN:        qlog.ECT1,
                        },
                        qlog.PacketReceived{
                                Header: qlog.PacketHeader{
@@ -766,14 +772,16 @@ func TestConnectionUnpackCoalescedPacket(t *testing.T) {
                                        PacketNumber:     protocol.PacketNumber(1338),
                                        Version:          protocol.Version1,
                                },
-                               Raw:    qlog.RawInfo{Length: int(packet2.Size()), PayloadLength: 1},
-                               Frames: []qlog.Frame{{Frame: &wire.PingFrame{}}},
-                               ECN:    qlog.ECT1,
+                               Raw:        qlog.RawInfo{Length: int(packet2.Size()), PayloadLength: 1},
+                               DatagramID: 42,
+                               Frames:     []qlog.Frame{{Frame: &wire.PingFrame{}}},
+                               ECN:        qlog.ECT1,
                        },
                        qlog.PacketDropped{
-                               Header:  qlog.PacketHeader{DestConnectionID: incorrectSrcConnID},
-                               Raw:     qlog.RawInfo{Length: int(packet3.Size())},
-                               Trigger: qlog.PacketDropUnknownConnectionID,
+                               Header:     qlog.PacketHeader{DestConnectionID: incorrectSrcConnID},
+                               Raw:        qlog.RawInfo{Length: int(packet3.Size())},
+                               DatagramID: 42,
+                               Trigger:    qlog.PacketDropUnknownConnectionID,
                        },
                },
                eventRecorder.Events(qlog.PacketReceived{}, qlog.PacketDropped{}),
@@ -1664,12 +1672,13 @@ func TestConnectionPacketBuffering(t *testing.T) {
                hdrs := make(map[string]*wire.ExtendedHeader)
 
                packet1 := getLongHeaderPacket(t, tc.remoteAddr, &hdr1, []byte("packet1"))
+               datagramID1 := qlog.CalculateDatagramID(packet1.data)
                hdrs["packet1"] = &hdr1
                tc.conn.handlePacket(packet1)
                packet2 := getLongHeaderPacket(t, tc.remoteAddr, &hdr2, []byte("packet2"))
-               tc.conn.handlePacket(packet2)
+               datagramID2 := qlog.CalculateDatagramID(packet2.data)
                hdrs["packet2"] = &hdr2
-
+               tc.conn.handlePacket(packet2)
                synctest.Wait()
 
                require.Equal(t,
@@ -1679,14 +1688,16 @@ func TestConnectionPacketBuffering(t *testing.T) {
                                                PacketType:   qlog.PacketTypeHandshake,
                                                PacketNumber: protocol.InvalidPacketNumber,
                                        },
-                                       Raw: qlog.RawInfo{Length: int(packet1.Size())},
+                                       Raw:        qlog.RawInfo{Length: int(packet1.Size())},
+                                       DatagramID: datagramID1,
                                },
                                qlog.PacketBuffered{
                                        Header: qlog.PacketHeader{
                                                PacketType:   qlog.PacketTypeHandshake,
                                                PacketNumber: protocol.InvalidPacketNumber,
                                        },
-                                       Raw: qlog.RawInfo{Length: int(packet2.Size())},
+                                       Raw:        qlog.RawInfo{Length: int(packet2.Size())},
+                                       DatagramID: datagramID2,
                                },
                        },
                        eventRecorder.Events(qlog.PacketBuffered{}),
@@ -1735,6 +1746,7 @@ func TestConnectionPacketBuffering(t *testing.T) {
                )
 
                packet3 := getLongHeaderPacket(t, tc.remoteAddr, &hdr3, []byte("packet3"))
+               datagramID3 := qlog.CalculateDatagramID(packet3.data)
                tc.conn.handlePacket(packet3)
 
                synctest.Wait()
@@ -1753,8 +1765,9 @@ func TestConnectionPacketBuffering(t *testing.T) {
                                                PacketNumber:     3,
                                                Version:          protocol.Version1,
                                        },
-                                       Raw:    qlog.RawInfo{Length: int(packet3.Size()), PayloadLength: 8},
-                                       Frames: []qlog.Frame{{Frame: &qlog.CryptoFrame{Length: 6}}},
+                                       Raw:        qlog.RawInfo{Length: int(packet3.Size()), PayloadLength: 8},
+                                       DatagramID: datagramID3,
+                                       Frames:     []qlog.Frame{{Frame: &qlog.CryptoFrame{Length: 6}}},
                                },
                                qlog.PacketReceived{
                                        Header: qlog.PacketHeader{
@@ -1764,8 +1777,9 @@ func TestConnectionPacketBuffering(t *testing.T) {
                                                PacketNumber:     1,
                                                Version:          protocol.Version1,
                                        },
-                                       Raw:    qlog.RawInfo{Length: int(packet1.Size()), PayloadLength: 8},
-                                       Frames: []qlog.Frame{},
+                                       Raw:        qlog.RawInfo{Length: int(packet1.Size()), PayloadLength: 8},
+                                       DatagramID: datagramID1,
+                                       Frames:     []qlog.Frame{},
                                },
                                qlog.PacketReceived{
                                        Header: qlog.PacketHeader{
@@ -1775,8 +1789,9 @@ func TestConnectionPacketBuffering(t *testing.T) {
                                                PacketNumber:     2,
                                                Version:          protocol.Version1,
                                        },
-                                       Raw:    qlog.RawInfo{Length: int(packet1.Size()), PayloadLength: 8},
-                                       Frames: []qlog.Frame{},
+                                       Raw:        qlog.RawInfo{Length: int(packet1.Size()), PayloadLength: 8},
+                                       DatagramID: datagramID2,
+                                       Frames:     []qlog.Frame{},
                                },
                        },
                        eventRecorder.Events(qlog.PacketReceived{}, qlog.PacketBuffered{}),
@@ -2825,7 +2840,7 @@ func TestConnectionVersionNegotiationInvalidPackets(t *testing.T) {
                tc.srcConnID,
                []protocol.Version{1234, protocol.Version1},
        )
-       wasProcessed, err := tc.conn.handleOnePacket(vnp)
+       wasProcessed, err := tc.conn.handleOnePacket(vnp, 0)
        require.NoError(t, err)
        require.False(t, wasProcessed)
        require.Equal(t,
@@ -2843,7 +2858,7 @@ func TestConnectionVersionNegotiationInvalidPackets(t *testing.T) {
 
        // unparseable, since it's missing 2 bytes
        vnp.data = vnp.data[:len(vnp.data)-2]
-       wasProcessed, err = tc.conn.handleOnePacket(vnp)
+       wasProcessed, err = tc.conn.handleOnePacket(vnp, 0)
        require.NoError(t, err)
        require.False(t, wasProcessed)
        require.Equal(t,
@@ -2894,7 +2909,7 @@ func TestConnectionRetryDrops(t *testing.T) {
        // invalid integrity tag
        retry := getRetryPacket(t, newConnID, tc.srcConnID, tc.destConnID, []byte("foobar"))
        retry.data[len(retry.data)-1]++
-       wasProcessed, err := tc.conn.handleOnePacket(retry)
+       wasProcessed, err := tc.conn.handleOnePacket(retry, 0)
        require.NoError(t, err)
        require.False(t, wasProcessed)
        require.Equal(t,
@@ -2916,7 +2931,7 @@ func TestConnectionRetryDrops(t *testing.T) {
 
        // receive a retry that doesn't change the connection ID
        retry = getRetryPacket(t, tc.destConnID, tc.srcConnID, tc.destConnID, []byte("foobar"))
-       wasProcessed, err = tc.conn.handleOnePacket(retry)
+       wasProcessed, err = tc.conn.handleOnePacket(retry, 0)
        require.NoError(t, err)
        require.False(t, wasProcessed)
        require.Equal(t,
@@ -2961,7 +2976,7 @@ func TestConnectionRetryAfterReceivedPacket(t *testing.T) {
                buffer:     getPacketBuffer(),
                rcvTime:    monotime.Now(),
                remoteAddr: tc.remoteAddr,
-       })
+       }, 0)
        require.NoError(t, err)
        require.True(t, wasProcessed)
 
@@ -2979,7 +2994,7 @@ func TestConnectionRetryAfterReceivedPacket(t *testing.T) {
 
        // receive a retry
        retry := getRetryPacket(t, tc.destConnID, tc.srcConnID, tc.destConnID, []byte("foobar"))
-       wasProcessed, err = tc.conn.handleOnePacket(retry)
+       wasProcessed, err = tc.conn.handleOnePacket(retry, 0)
        require.NoError(t, err)
        require.False(t, wasProcessed)
 
@@ -3106,8 +3121,9 @@ func testConnectionConnectionIDChanges(t *testing.T, sendRetry bool) {
                                                PacketNumber:     1,
                                                Version:          protocol.Version1,
                                        },
-                                       Raw:    qlog.RawInfo{Length: int(packet1.Size()), PayloadLength: int(hdr1.Length)},
-                                       Frames: []qlog.Frame{},
+                                       Raw:        qlog.RawInfo{Length: int(packet1.Size()), PayloadLength: int(hdr1.Length)},
+                                       DatagramID: qlog.CalculateDatagramID(packet1.data),
+                                       Frames:     []qlog.Frame{},
                                },
                        },
                        eventRecorder.Events(qlog.PacketReceived{}, qlog.PacketDropped{}),
@@ -3127,8 +3143,9 @@ func testConnectionConnectionIDChanges(t *testing.T, sendRetry bool) {
                                                PacketType:   qlog.PacketTypeInitial,
                                                PacketNumber: protocol.InvalidPacketNumber,
                                        },
-                                       Raw:     qlog.RawInfo{Length: int(packet2.Size())},
-                                       Trigger: qlog.PacketDropUnknownConnectionID,
+                                       Raw:        qlog.RawInfo{Length: int(packet2.Size())},
+                                       DatagramID: qlog.CalculateDatagramID(packet2.data),
+                                       Trigger:    qlog.PacketDropUnknownConnectionID,
                                },
                        },
                        eventRecorder.Events(qlog.PacketDropped{}, qlog.PacketReceived{}),
index 97d51368f2acffaa5d75b213b30c6494d1226237..83ca71f13aaac56f958db535d60985d4720f9b29 100644 (file)
@@ -214,6 +214,7 @@ func (e ConnectionClosed) Encode(enc *jsontext.Encoder, _ time.Time) error {
 type PacketSent struct {
        Header            PacketHeader
        Raw               RawInfo
+       DatagramID        DatagramID
        Frames            []Frame
        ECN               ECN
        IsCoalesced       bool
@@ -234,6 +235,10 @@ func (e PacketSent) Encode(enc *jsontext.Encoder, _ time.Time) error {
        if err := e.Raw.encode(enc); err != nil {
                return err
        }
+       if e.DatagramID != 0 {
+               h.WriteToken(jsontext.String("datagram_id"))
+               h.WriteToken(jsontext.Uint(uint64(e.DatagramID)))
+       }
        if len(e.Frames) > 0 {
                h.WriteToken(jsontext.String("frames"))
                if err := frames(e.Frames).encode(enc); err != nil {
@@ -259,6 +264,7 @@ func (e PacketSent) Encode(enc *jsontext.Encoder, _ time.Time) error {
 type PacketReceived struct {
        Header      PacketHeader
        Raw         RawInfo
+       DatagramID  DatagramID
        Frames      []Frame
        ECN         ECN
        IsCoalesced bool
@@ -278,6 +284,10 @@ func (e PacketReceived) Encode(enc *jsontext.Encoder, _ time.Time) error {
        if err := e.Raw.encode(enc); err != nil {
                return err
        }
+       if e.DatagramID != 0 {
+               h.WriteToken(jsontext.String("datagram_id"))
+               h.WriteToken(jsontext.Uint(uint64(e.DatagramID)))
+       }
        if len(e.Frames) > 0 {
                h.WriteToken(jsontext.String("frames"))
                if err := frames(e.Frames).encode(enc); err != nil {
@@ -345,8 +355,9 @@ func (e VersionNegotiationSent) Encode(enc *jsontext.Encoder, _ time.Time) error
 }
 
 type PacketBuffered struct {
-       Header PacketHeader
-       Raw    RawInfo
+       Header     PacketHeader
+       Raw        RawInfo
+       DatagramID DatagramID
 }
 
 func (e PacketBuffered) Name() string { return "transport:packet_buffered" }
@@ -362,6 +373,10 @@ func (e PacketBuffered) Encode(enc *jsontext.Encoder, _ time.Time) error {
        if err := e.Raw.encode(enc); err != nil {
                return err
        }
+       if e.DatagramID != 0 {
+               h.WriteToken(jsontext.String("datagram_id"))
+               h.WriteToken(jsontext.Uint(uint64(e.DatagramID)))
+       }
        h.WriteToken(jsontext.String("trigger"))
        h.WriteToken(jsontext.String("keys_unavailable"))
        h.WriteToken(jsontext.EndObject)
@@ -370,9 +385,10 @@ func (e PacketBuffered) Encode(enc *jsontext.Encoder, _ time.Time) error {
 
 // PacketDropped is the transport:packet_dropped event.
 type PacketDropped struct {
-       Header  PacketHeader
-       Raw     RawInfo
-       Trigger PacketDropReason
+       Header     PacketHeader
+       Raw        RawInfo
+       DatagramID DatagramID
+       Trigger    PacketDropReason
 }
 
 func (e PacketDropped) Name() string { return "transport:packet_dropped" }
@@ -388,6 +404,10 @@ func (e PacketDropped) Encode(enc *jsontext.Encoder, _ time.Time) error {
        if err := e.Raw.encode(enc); err != nil {
                return err
        }
+       if e.DatagramID != 0 {
+               h.WriteToken(jsontext.String("datagram_id"))
+               h.WriteToken(jsontext.Uint(uint64(e.DatagramID)))
+       }
        h.WriteToken(jsontext.String("trigger"))
        h.WriteToken(jsontext.String(string(e.Trigger)))
        h.WriteToken(jsontext.EndObject)
index 08d9cec019b8d82ad7a3e2599ea878315355c533..8ba09d4abab1a6ec9ee93801f6c8c6571827bd80 100644 (file)
@@ -399,6 +399,7 @@ func TestPacketSent(t *testing.T) {
        require.Equal(t, "transport:packet_sent", name)
        require.Contains(t, ev, "raw")
        raw := ev["raw"].(map[string]any)
+       require.NotContains(t, ev, "datagram_id")
        require.Equal(t, float64(987), raw["length"])
        require.Equal(t, float64(1337), raw["payload_length"])
        require.Contains(t, ev, "header")
@@ -414,7 +415,17 @@ func TestPacketSent(t *testing.T) {
        require.Equal(t, "stream", frames[1].(map[string]any)["frame_type"])
 }
 
-func TestPacketSentShort(t *testing.T) {
+func TestPacketSent1RTT(t *testing.T) {
+       t.Run("with datagram ID", func(t *testing.T) {
+               testPacketSent1RTT(t, 1337)
+       })
+
+       t.Run("without datagram ID", func(t *testing.T) {
+               testPacketSent1RTT(t, 0)
+       })
+}
+
+func testPacketSent1RTT(t *testing.T, datagramID DatagramID) {
        name, ev := testEventEncoding(t, &PacketSent{
                Header: PacketHeader{
                        PacketType:       PacketType1RTT,
@@ -427,7 +438,8 @@ func TestPacketSentShort(t *testing.T) {
                        {Frame: &AckFrame{AckRanges: []wire.AckRange{{Smallest: 1, Largest: 10}}}},
                        {Frame: &MaxDataFrame{MaximumData: 987}},
                },
-               ECN: ECNUnsupported,
+               ECN:        ECNUnsupported,
+               DatagramID: datagramID,
        })
 
        require.Equal(t, "transport:packet_sent", name)
@@ -444,6 +456,12 @@ func TestPacketSentShort(t *testing.T) {
        require.Len(t, frames, 2)
        require.Equal(t, "ack", frames[0].(map[string]any)["frame_type"])
        require.Equal(t, "max_data", frames[1].(map[string]any)["frame_type"])
+       if datagramID != 0 {
+               require.Contains(t, ev, "datagram_id")
+               require.Equal(t, float64(datagramID), ev["datagram_id"])
+       } else {
+               require.NotContains(t, ev, "datagram_id")
+       }
 }
 
 func TestPacketReceived(t *testing.T) {
@@ -464,7 +482,8 @@ func TestPacketReceived(t *testing.T) {
                        {Frame: &MaxStreamDataFrame{StreamID: 42, MaximumStreamData: 987}},
                        {Frame: &StreamFrame{StreamID: 123, Offset: 1234, Length: 6, Fin: true}},
                },
-               ECN: ECT0,
+               ECN:        ECT0,
+               DatagramID: 42,
        })
 
        require.Equal(t, "transport:packet_received", name)
@@ -483,9 +502,21 @@ func TestPacketReceived(t *testing.T) {
        require.Equal(t, "deadbeef", token["data"])
        require.Contains(t, ev, "frames")
        require.Len(t, ev["frames"].([]any), 2)
+       require.Contains(t, ev, "datagram_id")
+       require.Equal(t, float64(42), ev["datagram_id"])
 }
 
 func TestPacketReceived1RTT(t *testing.T) {
+       t.Run("with datagram ID", func(t *testing.T) {
+               testPacketReceived1RTT(t, 1337)
+       })
+
+       t.Run("without datagram ID", func(t *testing.T) {
+               testPacketReceived1RTT(t, 0)
+       })
+}
+
+func testPacketReceived1RTT(t *testing.T, datagramID DatagramID) {
        name, ev := testEventEncoding(t, &PacketReceived{
                Header: PacketHeader{
                        PacketType:       PacketType1RTT,
@@ -498,7 +529,8 @@ func TestPacketReceived1RTT(t *testing.T) {
                        {Frame: &MaxStreamDataFrame{StreamID: 42, MaximumStreamData: 987}},
                        {Frame: &StreamFrame{StreamID: 123, Offset: 1234, Length: 6, Fin: true}},
                },
-               ECN: ECT1,
+               ECN:        ECT1,
+               DatagramID: datagramID,
        })
 
        require.Equal(t, "transport:packet_received", name)
@@ -511,9 +543,14 @@ func TestPacketReceived1RTT(t *testing.T) {
        hdr := ev["header"].(map[string]any)
        require.Equal(t, "1RTT", hdr["packet_type"])
        require.Equal(t, float64(1337), hdr["packet_number"])
-       require.Equal(t, "0", hdr["key_phase_bit"])
        require.Contains(t, ev, "frames")
        require.Len(t, ev["frames"].([]any), 2)
+       if datagramID != 0 {
+               require.Contains(t, ev, "datagram_id")
+               require.Equal(t, float64(datagramID), ev["datagram_id"])
+       } else {
+               require.NotContains(t, ev, "datagram_id")
+       }
 }
 
 func TestPacketReceivedRetry(t *testing.T) {
index 4cd2bb64c650b253342bc113563732cbe00b9f26..dfa4066d27e39e8c87ecf64e6433f12a7127ddef 100644 (file)
@@ -2,6 +2,7 @@ package qlog
 
 import (
        "fmt"
+       "hash/crc32"
 
        "github.com/quic-go/quic-go/internal/protocol"
        "github.com/quic-go/quic-go/internal/qerr"
@@ -293,3 +294,11 @@ const (
        // StatelessReset indicates the connection was closed due to receiving a stateless reset from the peer
        ConnectionCloseTriggerStatelessReset ConnectionCloseTrigger = "stateless_reset"
 )
+
+// DatagramID is a unique identifier for a datagram
+type DatagramID uint32
+
+// CalculateDatagramID computes a DatagramID for a given packet
+func CalculateDatagramID(packet []byte) DatagramID {
+       return DatagramID(crc32.ChecksumIEEE(packet))
+}
index 15aaa4203afbf875953e4f61f0c8ecc266936723..ff3017ef337148dbb3612fb60c5f4c73ea9f552e 100644 (file)
@@ -14,3 +14,7 @@ func TestEncryptionLevelToPacketType(t *testing.T) {
        require.Equal(t, "0RTT", string(EncryptionLevelToPacketType(protocol.Encryption0RTT)))
        require.Equal(t, "1RTT", string(EncryptionLevelToPacketType(protocol.Encryption1RTT)))
 }
+
+func TestCalculateDatagramID(t *testing.T) {
+       require.Equal(t, DatagramID(0xcbf43926), CalculateDatagramID([]byte("123456789")))
+}