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)
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)
if !ok {

View file

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

View file

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

View file

@ -220,15 +220,15 @@ func (mr *MockConnectionTracerMockRecorder) ReceivedTransportParameters(arg0 int
}
// 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.Call(m, "ReceivedVersionNegotiationPacket", arg0, arg1)
m.ctrl.Call(m, "ReceivedVersionNegotiationPacket", arg0, arg1, arg2)
}
// 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()
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.

View file

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

View file

@ -119,5 +119,15 @@ var _ = Describe("Connection ID generation", func() {
c := ArbitraryLenConnectionID(make([]byte, 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)
RestoredTransportParameters(parameters *TransportParameters) // for 0-RTT
SentPacket(hdr *ExtendedHeader, size ByteCount, ack *AckFrame, frames []Frame)
ReceivedVersionNegotiationPacket(*Header, []VersionNumber)
ReceivedVersionNegotiationPacket(dest, src ArbitraryLenConnectionID, _ []VersionNumber)
ReceivedRetry(*Header)
ReceivedPacket(hdr *ExtendedHeader, size ByteCount, frames []Frame)
BufferedPacket(PacketType)

View file

@ -219,15 +219,15 @@ func (mr *MockConnectionTracerMockRecorder) ReceivedTransportParameters(arg0 int
}
// 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.Call(m, "ReceivedVersionNegotiationPacket", arg0, arg1)
m.ctrl.Call(m, "ReceivedVersionNegotiationPacket", arg0, arg1, arg2)
}
// 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()
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.

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 {
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() {
hdr := &Header{DestConnectionID: ConnectionID{1, 2, 3}}
tr1.EXPECT().ReceivedVersionNegotiationPacket(hdr, []VersionNumber{1337})
tr2.EXPECT().ReceivedVersionNegotiationPacket(hdr, []VersionNumber{1337})
tracer.ReceivedVersionNegotiationPacket(hdr, []VersionNumber{1337})
src := ArbitraryLenConnectionID{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}
dest := ArbitraryLenConnectionID{1, 2, 3, 4}
tr1.EXPECT().ReceivedVersionNegotiationPacket(dest, src, []VersionNumber{1337})
tr2.EXPECT().ReceivedVersionNegotiationPacket(dest, src, []VersionNumber{1337})
tracer.ReceivedVersionNegotiationPacket(dest, src, []VersionNumber{1337})
})
It("traces the ReceivedRetry event", func() {

View file

@ -31,12 +31,13 @@ func (n NullConnectionTracer) StartedConnection(local, remote net.Addr, srcConnI
func (n NullConnectionTracer) NegotiatedVersion(chosen VersionNumber, clientVersions, serverVersions []VersionNumber) {
}
func (n NullConnectionTracer) ClosedConnection(err error) {}
func (n NullConnectionTracer) SentTransportParameters(*TransportParameters) {}
func (n NullConnectionTracer) ReceivedTransportParameters(*TransportParameters) {}
func (n NullConnectionTracer) RestoredTransportParameters(*TransportParameters) {}
func (n NullConnectionTracer) SentPacket(*ExtendedHeader, ByteCount, *AckFrame, []Frame) {}
func (n NullConnectionTracer) ReceivedVersionNegotiationPacket(*Header, []VersionNumber) {}
func (n NullConnectionTracer) ClosedConnection(err error) {}
func (n NullConnectionTracer) SentTransportParameters(*TransportParameters) {}
func (n NullConnectionTracer) ReceivedTransportParameters(*TransportParameters) {}
func (n NullConnectionTracer) RestoredTransportParameters(*TransportParameters) {}
func (n NullConnectionTracer) SentPacket(*ExtendedHeader, ByteCount, *AckFrame, []Frame) {}
func (n NullConnectionTracer) ReceivedVersionNegotiationPacket(dest, src ArbitraryLenConnectionID, _ []VersionNumber) {
}
func (n NullConnectionTracer) ReceivedRetry(*Header) {}
func (n NullConnectionTracer) ReceivedPacket(hdr *ExtendedHeader, size ByteCount, frames []Frame) {}
func (n NullConnectionTracer) BufferedPacket(PacketType) {}

View file

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

View file

@ -72,7 +72,7 @@ func transformExtendedHeader(hdr *wire.ExtendedHeader) *packetHeader {
func (h packetHeader) MarshalJSONObject(enc *gojay.Encoder) {
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))
}
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
type packetHeaderWithType struct {
PacketType logging.PacketType

View file

@ -321,14 +321,17 @@ func (t *connectionTracer) ReceivedRetry(hdr *wire.Header) {
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))
for i, v := range versions {
ver[i] = versionNumber(v)
}
t.mutex.Lock()
t.recordEvent(time.Now(), &eventVersionNegotiationReceived{
Header: *transformHeader(hdr),
Header: packetHeaderVersionNegotiation{
SrcConnectionID: src,
DestConnectionID: dest,
},
SupportedVersions: ver,
})
t.mutex.Unlock()

View file

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