trace packets that are sent outside of a connection

This commit is contained in:
Marten Seemann 2020-07-16 08:20:36 +07:00
parent f10894a1ce
commit 0c551c893c
9 changed files with 99 additions and 0 deletions

View file

@ -10,6 +10,7 @@ import (
gomock "github.com/golang/mock/gomock"
protocol "github.com/lucas-clemente/quic-go/internal/protocol"
wire "github.com/lucas-clemente/quic-go/internal/wire"
logging "github.com/lucas-clemente/quic-go/logging"
)
@ -48,6 +49,18 @@ func (mr *MockTracerMockRecorder) DroppedPacket(arg0, arg1, arg2, arg3 interface
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DroppedPacket", reflect.TypeOf((*MockTracer)(nil).DroppedPacket), arg0, arg1, arg2, arg3)
}
// SentPacket mocks base method
func (m *MockTracer) SentPacket(arg0 net.Addr, arg1 *wire.Header, arg2 protocol.ByteCount, arg3 []logging.Frame) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "SentPacket", arg0, arg1, arg2, arg3)
}
// SentPacket indicates an expected call of SentPacket
func (mr *MockTracerMockRecorder) SentPacket(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SentPacket", reflect.TypeOf((*MockTracer)(nil).SentPacket), arg0, arg1, arg2, arg3)
}
// TracerForConnection mocks base method
func (m *MockTracer) TracerForConnection(arg0 protocol.Perspective, arg1 protocol.ConnectionID) logging.ConnectionTracer {
m.ctrl.T.Helper()

View file

@ -68,6 +68,8 @@ const (
Encryption1RTT EncryptionLevel = protocol.Encryption1RTT
// Encryption0RTT is the 0-RTT encryption level
Encryption0RTT EncryptionLevel = protocol.Encryption0RTT
// EncryptionNone is no encryption
EncryptionNone EncryptionLevel = protocol.EncryptionUnspecified
)
const (
@ -85,6 +87,7 @@ type Tracer interface {
// If nil is returned, tracing will be disabled for this connection.
TracerForConnection(p Perspective, odcid ConnectionID) ConnectionTracer
SentPacket(net.Addr, *Header, ByteCount, []Frame)
DroppedPacket(net.Addr, PacketType, ByteCount, PacketDropReason)
}

View file

@ -7,6 +7,7 @@ package logging
import (
gomock "github.com/golang/mock/gomock"
protocol "github.com/lucas-clemente/quic-go/internal/protocol"
wire "github.com/lucas-clemente/quic-go/internal/wire"
net "net"
reflect "reflect"
)
@ -46,6 +47,18 @@ func (mr *MockTracerMockRecorder) DroppedPacket(arg0, arg1, arg2, arg3 interface
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DroppedPacket", reflect.TypeOf((*MockTracer)(nil).DroppedPacket), arg0, arg1, arg2, arg3)
}
// SentPacket mocks base method
func (m *MockTracer) SentPacket(arg0 net.Addr, arg1 *wire.Header, arg2 protocol.ByteCount, arg3 []Frame) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "SentPacket", arg0, arg1, arg2, arg3)
}
// SentPacket indicates an expected call of SentPacket
func (mr *MockTracerMockRecorder) SentPacket(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SentPacket", reflect.TypeOf((*MockTracer)(nil).SentPacket), arg0, arg1, arg2, arg3)
}
// TracerForConnection mocks base method
func (m *MockTracer) TracerForConnection(arg0 protocol.Perspective, arg1 protocol.ConnectionID) ConnectionTracer {
m.ctrl.T.Helper()

View file

@ -32,6 +32,12 @@ func (m *tracerMultiplexer) TracerForConnection(p Perspective, odcid ConnectionI
return newConnectionMultiplexer(connTracers...)
}
func (m *tracerMultiplexer) SentPacket(remote net.Addr, hdr *Header, size ByteCount, frames []Frame) {
for _, t := range m.tracers {
t.SentPacket(remote, hdr, size, frames)
}
}
func (m *tracerMultiplexer) DroppedPacket(remote net.Addr, typ PacketType, size ByteCount, reason PacketDropReason) {
for _, t := range m.tracers {
t.DroppedPacket(remote, typ, size, reason)

View file

@ -56,6 +56,15 @@ var _ = Describe("Tracing", func() {
})
It("traces the PacketSent event", func() {
remote := &net.UDPAddr{IP: net.IPv4(4, 3, 2, 1)}
hdr := &Header{DestConnectionID: ConnectionID{1, 2, 3}}
f := &MaxDataFrame{MaximumData: 1337}
tr1.EXPECT().SentPacket(remote, hdr, ByteCount(1024), []Frame{f})
tr2.EXPECT().SentPacket(remote, hdr, ByteCount(1024), []Frame{f})
tracer.SentPacket(remote, hdr, 1024, []Frame{f})
})
It("traces the PacketDropped event", func() {
remote := &net.UDPAddr{IP: net.IPv4(4, 3, 2, 1)}
tr1.EXPECT().DroppedPacket(remote, PacketTypeRetry, ByteCount(1024), PacketDropDuplicate)
tr2.EXPECT().DroppedPacket(remote, PacketTypeRetry, ByteCount(1024), PacketDropDuplicate)

View file

@ -5,6 +5,7 @@ import (
"net"
"time"
"github.com/lucas-clemente/quic-go/internal/protocol"
"github.com/lucas-clemente/quic-go/logging"
"go.opencensus.io/stats"
@ -65,6 +66,16 @@ func (t *tracer) TracerForConnection(p logging.Perspective, _ logging.Connection
return newConnTracer(t, p)
}
func (t *tracer) SentPacket(_ net.Addr, hdr *logging.Header, _ protocol.ByteCount, _ []logging.Frame) {
stats.RecordWithTags(
context.Background(),
[]tag.Mutator{
tag.Upsert(keyPacketType, packetType(logging.PacketTypeFromHeader(hdr)).String()),
},
sentPackets.M(1),
)
}
func (t *tracer) DroppedPacket(net.Addr, logging.PacketType, logging.ByteCount, logging.PacketDropReason) {
}

View file

@ -37,6 +37,7 @@ func (t *tracer) TracerForConnection(p logging.Perspective, odcid protocol.Conne
return nil
}
func (t *tracer) SentPacket(net.Addr, *logging.Header, protocol.ByteCount, []logging.Frame) {}
func (t *tracer) DroppedPacket(net.Addr, logging.PacketType, protocol.ByteCount, logging.PacketDropReason) {
}

View file

@ -553,6 +553,9 @@ func (s *baseServer) sendRetry(remoteAddr net.Addr, hdr *wire.Header) error {
// append the Retry integrity tag
tag := handshake.GetRetryIntegrityTag(buf.Bytes(), hdr.DestConnectionID)
buf.Write(tag[:])
if s.config.Tracer != nil {
s.config.Tracer.SentPacket(remoteAddr, &replyHdr.Header, protocol.ByteCount(buf.Len()), nil)
}
_, err = s.conn.WriteTo(buf.Bytes(), remoteAddr)
return err
}
@ -627,6 +630,9 @@ func (s *baseServer) sendError(remoteAddr net.Addr, hdr *wire.Header, sealer han
replyHdr.Log(s.logger)
wire.LogFrame(s.logger, ccf, true)
if s.config.Tracer != nil {
s.config.Tracer.SentPacket(remoteAddr, &replyHdr.Header, protocol.ByteCount(len(raw)), []logging.Frame{ccf})
}
_, err := s.conn.WriteTo(raw, remoteAddr)
return err
}
@ -638,6 +644,18 @@ func (s *baseServer) sendVersionNegotiationPacket(p *receivedPacket, hdr *wire.H
s.logger.Debugf("Error composing Version Negotiation: %s", err)
return
}
if s.config.Tracer != nil {
s.config.Tracer.SentPacket(
p.remoteAddr,
&wire.Header{
IsLongHeader: true,
DestConnectionID: hdr.SrcConnectionID,
SrcConnectionID: hdr.DestConnectionID,
},
protocol.ByteCount(len(data)),
nil,
)
}
if _, err := s.conn.WriteTo(data, p.remoteAddr); err != nil {
s.logger.Debugf("Error sending Version Negotiation: %s", err)
}

View file

@ -261,6 +261,7 @@ var _ = Describe("Server", func() {
Version: serv.config.Versions[0],
}, make([]byte, protocol.MinInitialPacketSize))
packet.remoteAddr = raddr
tracer.EXPECT().SentPacket(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).MaxTimes(1)
serv.handlePacket(packet)
Eventually(done).Should(BeClosed())
})
@ -284,6 +285,7 @@ var _ = Describe("Server", func() {
Version: serv.config.Versions[0],
}, make([]byte, protocol.MinInitialPacketSize))
packet.remoteAddr = raddr
tracer.EXPECT().SentPacket(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).MaxTimes(1)
serv.handlePacket(packet)
Eventually(done).Should(BeClosed())
})
@ -379,6 +381,12 @@ var _ = Describe("Server", func() {
Version: 0x42,
}, make([]byte, protocol.MinInitialPacketSize))
packet.remoteAddr = &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 1337}
tracer.EXPECT().SentPacket(packet.remoteAddr, gomock.Any(), gomock.Any(), nil).Do(func(_ net.Addr, replyHdr *logging.Header, _ logging.ByteCount, _ []logging.Frame) {
Expect(replyHdr.IsLongHeader).To(BeTrue())
Expect(replyHdr.Version).To(BeZero())
Expect(replyHdr.SrcConnectionID).To(Equal(destConnID))
Expect(replyHdr.DestConnectionID).To(Equal(srcConnID))
})
serv.handlePacket(packet)
var write mockPacketConnWrite
Eventually(conn.dataWritten).Should(Receive(&write))
@ -402,6 +410,12 @@ var _ = Describe("Server", func() {
}
packet := getPacket(hdr, make([]byte, protocol.MinInitialPacketSize))
packet.remoteAddr = &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 1337}
tracer.EXPECT().SentPacket(packet.remoteAddr, gomock.Any(), gomock.Any(), nil).Do(func(_ net.Addr, replyHdr *logging.Header, _ logging.ByteCount, _ []logging.Frame) {
Expect(replyHdr.Type).To(Equal(protocol.PacketTypeRetry))
Expect(replyHdr.SrcConnectionID).ToNot(Equal(hdr.DestConnectionID))
Expect(replyHdr.DestConnectionID).To(Equal(hdr.SrcConnectionID))
Expect(replyHdr.Token).ToNot(BeEmpty())
})
serv.handlePacket(packet)
var write mockPacketConnWrite
Eventually(conn.dataWritten).Should(Receive(&write))
@ -429,6 +443,16 @@ var _ = Describe("Server", func() {
packet := getPacket(hdr, make([]byte, protocol.MinInitialPacketSize))
packet.data = append(packet.data, []byte("coalesced packet")...) // add some garbage to simulate a coalesced packet
packet.remoteAddr = &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 1337}
tracer.EXPECT().SentPacket(packet.remoteAddr, gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ net.Addr, replyHdr *logging.Header, _ logging.ByteCount, frames []logging.Frame) {
Expect(replyHdr.Type).To(Equal(protocol.PacketTypeInitial))
Expect(replyHdr.SrcConnectionID).To(Equal(hdr.DestConnectionID))
Expect(replyHdr.DestConnectionID).To(Equal(hdr.SrcConnectionID))
Expect(frames).To(HaveLen(1))
Expect(frames[0]).To(BeAssignableToTypeOf(&wire.ConnectionCloseFrame{}))
ccf := frames[0].(*logging.ConnectionCloseFrame)
Expect(ccf.IsApplicationError).To(BeFalse())
Expect(ccf.ErrorCode).To(Equal(qerr.InvalidToken))
})
serv.handlePacket(packet)
var write mockPacketConnWrite
Eventually(conn.dataWritten).Should(Receive(&write))
@ -740,6 +764,7 @@ var _ = Describe("Server", func() {
p := getInitialWithRandomDestConnID()
hdr, _, _, err := wire.ParsePacket(p.data, 0)
Expect(err).ToNot(HaveOccurred())
tracer.EXPECT().SentPacket(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
serv.handlePacket(p)
var reject mockPacketConnWrite
Eventually(conn.dataWritten).Should(Receive(&reject))