trace arbitrary length Connection IDs for Version Negotiation packets

This commit is contained in:
Marten Seemann 2022-08-28 14:12:43 +03:00
parent ecc8320c2c
commit 53412e9ba3
15 changed files with 75 additions and 38 deletions

View file

@ -1094,7 +1094,11 @@ func (s *connection) handleVersionNegotiationPacket(p *receivedPacket) {
s.logger.Infof("Received a Version Negotiation packet. Supported Versions: %s", supportedVersions) s.logger.Infof("Received a Version Negotiation packet. Supported Versions: %s", supportedVersions)
if s.tracer != nil { if s.tracer != nil {
s.tracer.ReceivedVersionNegotiationPacket(hdr, supportedVersions) s.tracer.ReceivedVersionNegotiationPacket(
protocol.ArbitraryLenConnectionID(hdr.DestConnectionID),
protocol.ArbitraryLenConnectionID(hdr.SrcConnectionID),
supportedVersions,
)
} }
newVersion, ok := protocol.ChooseSupportedVersion(s.config.Versions, supportedVersions) newVersion, ok := protocol.ChooseSupportedVersion(s.config.Versions, supportedVersions)
if !ok { if !ok {

View file

@ -2613,8 +2613,7 @@ var _ = Describe("Client Connection", func() {
errChan <- conn.run() errChan <- conn.run()
}() }()
connRunner.EXPECT().Remove(srcConnID) connRunner.EXPECT().Remove(srcConnID)
tracer.EXPECT().ReceivedVersionNegotiationPacket(gomock.Any(), gomock.Any()).Do(func(hdr *wire.Header, versions []logging.VersionNumber) { tracer.EXPECT().ReceivedVersionNegotiationPacket(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_, _ protocol.ArbitraryLenConnectionID, versions []logging.VersionNumber) {
Expect(hdr.Version).To(BeZero())
Expect(versions).To(And( Expect(versions).To(And(
ContainElement(protocol.VersionNumber(4321)), ContainElement(protocol.VersionNumber(4321)),
ContainElement(protocol.VersionNumber(1337)), ContainElement(protocol.VersionNumber(1337)),
@ -2640,7 +2639,7 @@ var _ = Describe("Client Connection", func() {
}() }()
connRunner.EXPECT().Remove(srcConnID).MaxTimes(1) connRunner.EXPECT().Remove(srcConnID).MaxTimes(1)
gomock.InOrder( gomock.InOrder(
tracer.EXPECT().ReceivedVersionNegotiationPacket(gomock.Any(), gomock.Any()), tracer.EXPECT().ReceivedVersionNegotiationPacket(gomock.Any(), gomock.Any(), gomock.Any()),
tracer.EXPECT().ClosedConnection(gomock.Any()).Do(func(e error) { tracer.EXPECT().ClosedConnection(gomock.Any()).Do(func(e error) {
var vnErr *VersionNegotiationError var vnErr *VersionNegotiationError
Expect(errors.As(e, &vnErr)).To(BeTrue()) Expect(errors.As(e, &vnErr)).To(BeTrue())

View file

@ -58,6 +58,8 @@ type versionNegotiationTracer struct {
clientVersions, serverVersions []logging.VersionNumber clientVersions, serverVersions []logging.VersionNumber
} }
var _ logging.ConnectionTracer = &versionNegotiationTracer{}
func (t *versionNegotiationTracer) NegotiatedVersion(chosen logging.VersionNumber, clientVersions, serverVersions []logging.VersionNumber) { func (t *versionNegotiationTracer) NegotiatedVersion(chosen logging.VersionNumber, clientVersions, serverVersions []logging.VersionNumber) {
if t.loggedVersions { if t.loggedVersions {
Fail("only expected one call to NegotiatedVersions") Fail("only expected one call to NegotiatedVersions")
@ -68,7 +70,7 @@ func (t *versionNegotiationTracer) NegotiatedVersion(chosen logging.VersionNumbe
t.serverVersions = serverVersions t.serverVersions = serverVersions
} }
func (t *versionNegotiationTracer) ReceivedVersionNegotiationPacket(*logging.Header, []logging.VersionNumber) { func (t *versionNegotiationTracer) ReceivedVersionNegotiationPacket(dest, src logging.ArbitraryLenConnectionID, _ []logging.VersionNumber) {
t.receivedVersionNegotiation = true t.receivedVersionNegotiation = true
} }

View file

@ -220,15 +220,15 @@ func (mr *MockConnectionTracerMockRecorder) ReceivedTransportParameters(arg0 int
} }
// ReceivedVersionNegotiationPacket mocks base method. // ReceivedVersionNegotiationPacket mocks base method.
func (m *MockConnectionTracer) ReceivedVersionNegotiationPacket(arg0 *wire.Header, arg1 []protocol.VersionNumber) { func (m *MockConnectionTracer) ReceivedVersionNegotiationPacket(arg0, arg1 protocol.ArbitraryLenConnectionID, arg2 []protocol.VersionNumber) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
m.ctrl.Call(m, "ReceivedVersionNegotiationPacket", arg0, arg1) m.ctrl.Call(m, "ReceivedVersionNegotiationPacket", arg0, arg1, arg2)
} }
// ReceivedVersionNegotiationPacket indicates an expected call of ReceivedVersionNegotiationPacket. // ReceivedVersionNegotiationPacket indicates an expected call of ReceivedVersionNegotiationPacket.
func (mr *MockConnectionTracerMockRecorder) ReceivedVersionNegotiationPacket(arg0, arg1 interface{}) *gomock.Call { func (mr *MockConnectionTracerMockRecorder) ReceivedVersionNegotiationPacket(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReceivedVersionNegotiationPacket", reflect.TypeOf((*MockConnectionTracer)(nil).ReceivedVersionNegotiationPacket), arg0, arg1) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReceivedVersionNegotiationPacket", reflect.TypeOf((*MockConnectionTracer)(nil).ReceivedVersionNegotiationPacket), arg0, arg1, arg2)
} }
// RestoredTransportParameters mocks base method. // RestoredTransportParameters mocks base method.

View file

@ -20,6 +20,13 @@ func (c ArbitraryLenConnectionID) Bytes() []byte {
return c return c
} }
func (c ArbitraryLenConnectionID) String() string {
if c.Len() == 0 {
return "(empty)"
}
return fmt.Sprintf("%x", c.Bytes())
}
// A ConnectionID in QUIC // A ConnectionID in QUIC
type ConnectionID []byte type ConnectionID []byte

View file

@ -119,5 +119,15 @@ var _ = Describe("Connection ID generation", func() {
c := ArbitraryLenConnectionID(make([]byte, 156)) c := ArbitraryLenConnectionID(make([]byte, 156))
Expect(c.Len()).To(Equal(156)) Expect(c.Len()).To(Equal(156))
}) })
It("has a string representation", func() {
c := ArbitraryLenConnectionID([]byte{0xde, 0xad, 0xbe, 0xef, 0x42})
Expect(c.String()).To(Equal("deadbeef42"))
})
It("has a string representation for the default value", func() {
var c ArbitraryLenConnectionID
Expect(c.String()).To(Equal("(empty)"))
})
}) })
}) })

View file

@ -114,7 +114,7 @@ type ConnectionTracer interface {
ReceivedTransportParameters(*TransportParameters) ReceivedTransportParameters(*TransportParameters)
RestoredTransportParameters(parameters *TransportParameters) // for 0-RTT RestoredTransportParameters(parameters *TransportParameters) // for 0-RTT
SentPacket(hdr *ExtendedHeader, size ByteCount, ack *AckFrame, frames []Frame) SentPacket(hdr *ExtendedHeader, size ByteCount, ack *AckFrame, frames []Frame)
ReceivedVersionNegotiationPacket(*Header, []VersionNumber) ReceivedVersionNegotiationPacket(dest, src ArbitraryLenConnectionID, _ []VersionNumber)
ReceivedRetry(*Header) ReceivedRetry(*Header)
ReceivedPacket(hdr *ExtendedHeader, size ByteCount, frames []Frame) ReceivedPacket(hdr *ExtendedHeader, size ByteCount, frames []Frame)
BufferedPacket(PacketType) BufferedPacket(PacketType)

View file

@ -219,15 +219,15 @@ func (mr *MockConnectionTracerMockRecorder) ReceivedTransportParameters(arg0 int
} }
// ReceivedVersionNegotiationPacket mocks base method. // ReceivedVersionNegotiationPacket mocks base method.
func (m *MockConnectionTracer) ReceivedVersionNegotiationPacket(arg0 *wire.Header, arg1 []protocol.VersionNumber) { func (m *MockConnectionTracer) ReceivedVersionNegotiationPacket(arg0, arg1 protocol.ArbitraryLenConnectionID, arg2 []protocol.VersionNumber) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
m.ctrl.Call(m, "ReceivedVersionNegotiationPacket", arg0, arg1) m.ctrl.Call(m, "ReceivedVersionNegotiationPacket", arg0, arg1, arg2)
} }
// ReceivedVersionNegotiationPacket indicates an expected call of ReceivedVersionNegotiationPacket. // ReceivedVersionNegotiationPacket indicates an expected call of ReceivedVersionNegotiationPacket.
func (mr *MockConnectionTracerMockRecorder) ReceivedVersionNegotiationPacket(arg0, arg1 interface{}) *gomock.Call { func (mr *MockConnectionTracerMockRecorder) ReceivedVersionNegotiationPacket(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReceivedVersionNegotiationPacket", reflect.TypeOf((*MockConnectionTracer)(nil).ReceivedVersionNegotiationPacket), arg0, arg1) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReceivedVersionNegotiationPacket", reflect.TypeOf((*MockConnectionTracer)(nil).ReceivedVersionNegotiationPacket), arg0, arg1, arg2)
} }
// RestoredTransportParameters mocks base method. // RestoredTransportParameters mocks base method.

View file

@ -110,9 +110,9 @@ func (m *connTracerMultiplexer) SentPacket(hdr *ExtendedHeader, size ByteCount,
} }
} }
func (m *connTracerMultiplexer) ReceivedVersionNegotiationPacket(hdr *Header, versions []VersionNumber) { func (m *connTracerMultiplexer) ReceivedVersionNegotiationPacket(dest, src ArbitraryLenConnectionID, versions []VersionNumber) {
for _, t := range m.tracers { for _, t := range m.tracers {
t.ReceivedVersionNegotiationPacket(hdr, versions) t.ReceivedVersionNegotiationPacket(dest, src, versions)
} }
} }

View file

@ -159,10 +159,11 @@ var _ = Describe("Tracing", func() {
}) })
It("traces the ReceivedVersionNegotiationPacket event", func() { It("traces the ReceivedVersionNegotiationPacket event", func() {
hdr := &Header{DestConnectionID: ConnectionID{1, 2, 3}} src := ArbitraryLenConnectionID{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}
tr1.EXPECT().ReceivedVersionNegotiationPacket(hdr, []VersionNumber{1337}) dest := ArbitraryLenConnectionID{1, 2, 3, 4}
tr2.EXPECT().ReceivedVersionNegotiationPacket(hdr, []VersionNumber{1337}) tr1.EXPECT().ReceivedVersionNegotiationPacket(dest, src, []VersionNumber{1337})
tracer.ReceivedVersionNegotiationPacket(hdr, []VersionNumber{1337}) tr2.EXPECT().ReceivedVersionNegotiationPacket(dest, src, []VersionNumber{1337})
tracer.ReceivedVersionNegotiationPacket(dest, src, []VersionNumber{1337})
}) })
It("traces the ReceivedRetry event", func() { It("traces the ReceivedRetry event", func() {

View file

@ -36,7 +36,8 @@ func (n NullConnectionTracer) SentTransportParameters(*TransportParameters)
func (n NullConnectionTracer) ReceivedTransportParameters(*TransportParameters) {} func (n NullConnectionTracer) ReceivedTransportParameters(*TransportParameters) {}
func (n NullConnectionTracer) RestoredTransportParameters(*TransportParameters) {} func (n NullConnectionTracer) RestoredTransportParameters(*TransportParameters) {}
func (n NullConnectionTracer) SentPacket(*ExtendedHeader, ByteCount, *AckFrame, []Frame) {} func (n NullConnectionTracer) SentPacket(*ExtendedHeader, ByteCount, *AckFrame, []Frame) {}
func (n NullConnectionTracer) ReceivedVersionNegotiationPacket(*Header, []VersionNumber) {} func (n NullConnectionTracer) ReceivedVersionNegotiationPacket(dest, src ArbitraryLenConnectionID, _ []VersionNumber) {
}
func (n NullConnectionTracer) ReceivedRetry(*Header) {} func (n NullConnectionTracer) ReceivedRetry(*Header) {}
func (n NullConnectionTracer) ReceivedPacket(hdr *ExtendedHeader, size ByteCount, frames []Frame) {} func (n NullConnectionTracer) ReceivedPacket(hdr *ExtendedHeader, size ByteCount, frames []Frame) {}
func (n NullConnectionTracer) BufferedPacket(PacketType) {} func (n NullConnectionTracer) BufferedPacket(PacketType) {}

View file

@ -212,7 +212,7 @@ func (e eventRetryReceived) MarshalJSONObject(enc *gojay.Encoder) {
} }
type eventVersionNegotiationReceived struct { type eventVersionNegotiationReceived struct {
Header packetHeader Header packetHeaderVersionNegotiation
SupportedVersions []versionNumber SupportedVersions []versionNumber
} }

View file

@ -72,7 +72,7 @@ func transformExtendedHeader(hdr *wire.ExtendedHeader) *packetHeader {
func (h packetHeader) MarshalJSONObject(enc *gojay.Encoder) { func (h packetHeader) MarshalJSONObject(enc *gojay.Encoder) {
enc.StringKey("packet_type", packetType(h.PacketType).String()) enc.StringKey("packet_type", packetType(h.PacketType).String())
if h.PacketType != logging.PacketTypeRetry && h.PacketType != logging.PacketTypeVersionNegotiation { if h.PacketType != logging.PacketTypeRetry {
enc.Int64Key("packet_number", int64(h.PacketNumber)) enc.Int64Key("packet_number", int64(h.PacketNumber))
} }
if h.Version != 0 { if h.Version != 0 {
@ -96,6 +96,20 @@ func (h packetHeader) MarshalJSONObject(enc *gojay.Encoder) {
} }
} }
type packetHeaderVersionNegotiation struct {
SrcConnectionID logging.ArbitraryLenConnectionID
DestConnectionID logging.ArbitraryLenConnectionID
}
func (h packetHeaderVersionNegotiation) IsNil() bool { return false }
func (h packetHeaderVersionNegotiation) MarshalJSONObject(enc *gojay.Encoder) {
enc.StringKey("packet_type", "version_negotiation")
enc.IntKey("scil", h.SrcConnectionID.Len())
enc.StringKey("scid", h.SrcConnectionID.String())
enc.IntKey("dcil", h.DestConnectionID.Len())
enc.StringKey("dcid", h.DestConnectionID.String())
}
// a minimal header that only outputs the packet type // a minimal header that only outputs the packet type
type packetHeaderWithType struct { type packetHeaderWithType struct {
PacketType logging.PacketType PacketType logging.PacketType

View file

@ -321,14 +321,17 @@ func (t *connectionTracer) ReceivedRetry(hdr *wire.Header) {
t.mutex.Unlock() t.mutex.Unlock()
} }
func (t *connectionTracer) ReceivedVersionNegotiationPacket(hdr *wire.Header, versions []logging.VersionNumber) { func (t *connectionTracer) ReceivedVersionNegotiationPacket(dest, src logging.ArbitraryLenConnectionID, versions []logging.VersionNumber) {
ver := make([]versionNumber, len(versions)) ver := make([]versionNumber, len(versions))
for i, v := range versions { for i, v := range versions {
ver[i] = versionNumber(v) ver[i] = versionNumber(v)
} }
t.mutex.Lock() t.mutex.Lock()
t.recordEvent(time.Now(), &eventVersionNegotiationReceived{ t.recordEvent(time.Now(), &eventVersionNegotiationReceived{
Header: *transformHeader(hdr), Header: packetHeaderVersionNegotiation{
SrcConnectionID: src,
DestConnectionID: dest,
},
SupportedVersions: ver, SupportedVersions: ver,
}) })
t.mutex.Unlock() t.mutex.Unlock()

View file

@ -548,12 +548,8 @@ var _ = Describe("Tracing", func() {
It("records a received Version Negotiation packet", func() { It("records a received Version Negotiation packet", func() {
tracer.ReceivedVersionNegotiationPacket( tracer.ReceivedVersionNegotiationPacket(
&logging.Header{ protocol.ArbitraryLenConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
IsLongHeader: true, protocol.ArbitraryLenConnectionID{4, 3, 2, 1},
Type: protocol.PacketTypeRetry,
DestConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
SrcConnectionID: protocol.ConnectionID{4, 3, 2, 1},
},
[]protocol.VersionNumber{0xdeadbeef, 0xdecafbad}, []protocol.VersionNumber{0xdeadbeef, 0xdecafbad},
) )
entry := exportAndParseSingle() entry := exportAndParseSingle()
@ -568,8 +564,8 @@ var _ = Describe("Tracing", func() {
Expect(header).To(HaveKeyWithValue("packet_type", "version_negotiation")) Expect(header).To(HaveKeyWithValue("packet_type", "version_negotiation"))
Expect(header).ToNot(HaveKey("packet_number")) Expect(header).ToNot(HaveKey("packet_number"))
Expect(header).ToNot(HaveKey("version")) Expect(header).ToNot(HaveKey("version"))
Expect(header).To(HaveKey("dcid")) Expect(header).To(HaveKeyWithValue("dcid", "0102030405060708"))
Expect(header).To(HaveKey("scid")) Expect(header).To(HaveKeyWithValue("scid", "04030201"))
}) })
It("records buffered packets", func() { It("records buffered packets", func() {